blob: 365f0758b7610871cca0eb58b44fbdeaa00fc708 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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/verifier.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include <algorithm>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include <deque>
9#include <queue>
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010#include <sstream>
11#include <string>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013#include "src/bit-vector.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014#include "src/compiler/all-nodes.h"
15#include "src/compiler/common-operator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016#include "src/compiler/graph.h"
17#include "src/compiler/node.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018#include "src/compiler/node-properties.h"
19#include "src/compiler/opcodes.h"
20#include "src/compiler/operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021#include "src/compiler/operator-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022#include "src/compiler/schedule.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023#include "src/compiler/simplified-operator.h"
24#include "src/ostreams.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025
26namespace v8 {
27namespace internal {
28namespace compiler {
29
30
31static bool IsDefUseChainLinkPresent(Node* def, Node* use) {
Ben Murdochda12d292016-06-02 14:46:10 +010032 const Node::Uses uses = def->uses();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033 return std::find(uses.begin(), uses.end(), use) != uses.end();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034}
35
36
37static bool IsUseDefChainLinkPresent(Node* def, Node* use) {
Ben Murdochda12d292016-06-02 14:46:10 +010038 const Node::Inputs inputs = use->inputs();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039 return std::find(inputs.begin(), inputs.end(), def) != inputs.end();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040}
41
42
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043class Verifier::Visitor {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 public:
Ben Murdochc5610432016-08-08 18:44:38 +010045 Visitor(Zone* z, Typing typed, CheckInputs check_inputs)
46 : zone(z), typing(typed), check_inputs(check_inputs) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000048 void Check(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050 Zone* zone;
51 Typing typing;
Ben Murdochc5610432016-08-08 18:44:38 +010052 CheckInputs check_inputs;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040053
54 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040055 void CheckNotTyped(Node* node) {
56 if (NodeProperties::IsTyped(node)) {
57 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 str << "TypeError: node #" << node->id() << ":" << *node->op()
59 << " should never have a type";
60 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040061 }
62 }
63 void CheckUpperIs(Node* node, Type* type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 if (typing == TYPED && !NodeProperties::GetType(node)->Is(type)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040065 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 str << "TypeError: node #" << node->id() << ":" << *node->op()
67 << " type ";
68 NodeProperties::GetType(node)->PrintTo(str);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040069 str << " is not ";
70 type->PrintTo(str);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072 }
73 }
74 void CheckUpperMaybe(Node* node, Type* type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 if (typing == TYPED && !NodeProperties::GetType(node)->Maybe(type)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040076 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077 str << "TypeError: node #" << node->id() << ":" << *node->op()
78 << " type ";
79 NodeProperties::GetType(node)->PrintTo(str);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040080 str << " must intersect ";
81 type->PrintTo(str);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040083 }
84 }
85 void CheckValueInputIs(Node* node, int i, Type* type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086 Node* input = NodeProperties::GetValueInput(node, i);
87 if (typing == TYPED && !NodeProperties::GetType(input)->Is(type)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040088 std::ostringstream str;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000089 str << "TypeError: node #" << node->id() << ":" << *node->op()
90 << "(input @" << i << " = " << input->opcode() << ":"
91 << input->op()->mnemonic() << ") type ";
92 NodeProperties::GetType(input)->PrintTo(str);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040093 str << " is not ";
94 type->PrintTo(str);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095 FATAL(str.str().c_str());
96 }
97 }
98 void CheckOutput(Node* node, Node* use, int count, const char* kind) {
99 if (count <= 0) {
100 std::ostringstream str;
101 str << "GraphError: node #" << node->id() << ":" << *node->op()
102 << " does not produce " << kind << " output used by node #"
103 << use->id() << ":" << *use->op();
104 FATAL(str.str().c_str());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400105 }
106 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107};
108
109
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110void Verifier::Visitor::Check(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400111 int value_count = node->op()->ValueInputCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 int context_count = OperatorProperties::GetContextInputCount(node->op());
113 int frame_state_count =
114 OperatorProperties::GetFrameStateInputCount(node->op());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400115 int effect_count = node->op()->EffectInputCount();
116 int control_count = node->op()->ControlInputCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117
118 // Verify number of inputs matches up.
Ben Murdochc5610432016-08-08 18:44:38 +0100119 int input_count = value_count + context_count + frame_state_count;
120 if (check_inputs == kAll) {
121 input_count += effect_count + control_count;
122 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123 CHECK_EQ(input_count, node->InputCount());
124
125 // Verify that frame state has been inserted for the nodes that need it.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 for (int i = 0; i < frame_state_count; i++) {
127 Node* frame_state = NodeProperties::GetFrameStateInput(node, i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128 CHECK(frame_state->opcode() == IrOpcode::kFrameState ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 // kFrameState uses Start as a sentinel.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000130 (node->opcode() == IrOpcode::kFrameState &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 frame_state->opcode() == IrOpcode::kStart));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000132 CHECK(IsDefUseChainLinkPresent(frame_state, node));
133 CHECK(IsUseDefChainLinkPresent(frame_state, node));
134 }
135
136 // Verify all value inputs actually produce a value.
137 for (int i = 0; i < value_count; ++i) {
138 Node* value = NodeProperties::GetValueInput(node, i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 CheckOutput(value, node, value->op()->ValueOutputCount(), "value");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140 CHECK(IsDefUseChainLinkPresent(value, node));
141 CHECK(IsUseDefChainLinkPresent(value, node));
Ben Murdochda12d292016-06-02 14:46:10 +0100142 // Verify that only parameters and projections can have input nodes with
143 // multiple outputs.
144 CHECK(node->opcode() == IrOpcode::kParameter ||
145 node->opcode() == IrOpcode::kProjection ||
146 value->op()->ValueOutputCount() <= 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000147 }
148
149 // Verify all context inputs are value nodes.
150 for (int i = 0; i < context_count; ++i) {
151 Node* context = NodeProperties::GetContextInput(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 CheckOutput(context, node, context->op()->ValueOutputCount(), "context");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153 CHECK(IsDefUseChainLinkPresent(context, node));
154 CHECK(IsUseDefChainLinkPresent(context, node));
155 }
156
Ben Murdochc5610432016-08-08 18:44:38 +0100157 if (check_inputs == kAll) {
158 // Verify all effect inputs actually have an effect.
159 for (int i = 0; i < effect_count; ++i) {
160 Node* effect = NodeProperties::GetEffectInput(node);
161 CheckOutput(effect, node, effect->op()->EffectOutputCount(), "effect");
162 CHECK(IsDefUseChainLinkPresent(effect, node));
163 CHECK(IsUseDefChainLinkPresent(effect, node));
164 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000165
Ben Murdochc5610432016-08-08 18:44:38 +0100166 // Verify all control inputs are control nodes.
167 for (int i = 0; i < control_count; ++i) {
168 Node* control = NodeProperties::GetControlInput(node, i);
169 CheckOutput(control, node, control->op()->ControlOutputCount(),
170 "control");
171 CHECK(IsDefUseChainLinkPresent(control, node));
172 CHECK(IsUseDefChainLinkPresent(control, node));
173 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174 }
175
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 switch (node->opcode()) {
177 case IrOpcode::kStart:
178 // Start has no inputs.
179 CHECK_EQ(0, input_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400180 // Type is a tuple.
181 // TODO(rossberg): Multiple outputs are currently typed as Internal.
182 CheckUpperIs(node, Type::Internal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 break;
184 case IrOpcode::kEnd:
185 // End has no outputs.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186 CHECK(node->op()->ValueOutputCount() == 0);
187 CHECK(node->op()->EffectOutputCount() == 0);
188 CHECK(node->op()->ControlOutputCount() == 0);
189 // Type is empty.
190 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191 break;
192 case IrOpcode::kDead:
193 // Dead is never connected to the graph.
194 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 case IrOpcode::kBranch: {
197 // Branch uses are IfTrue and IfFalse.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400198 int count_true = 0, count_false = 0;
Ben Murdochda12d292016-06-02 14:46:10 +0100199 for (const Node* use : node->uses()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 CHECK(use->opcode() == IrOpcode::kIfTrue ||
201 use->opcode() == IrOpcode::kIfFalse);
202 if (use->opcode() == IrOpcode::kIfTrue) ++count_true;
203 if (use->opcode() == IrOpcode::kIfFalse) ++count_false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205 CHECK_EQ(1, count_true);
206 CHECK_EQ(1, count_false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400207 // Type is empty.
208 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 break;
210 }
211 case IrOpcode::kIfTrue:
212 case IrOpcode::kIfFalse:
213 CHECK_EQ(IrOpcode::kBranch,
214 NodeProperties::GetControlInput(node, 0)->opcode());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400215 // Type is empty.
216 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 case IrOpcode::kIfSuccess: {
219 // IfSuccess and IfException continuation only on throwing nodes.
220 Node* input = NodeProperties::GetControlInput(node, 0);
221 CHECK(!input->op()->HasProperty(Operator::kNoThrow));
222 // Type is empty.
223 CheckNotTyped(node);
224 break;
225 }
226 case IrOpcode::kIfException: {
227 // IfSuccess and IfException continuation only on throwing nodes.
228 Node* input = NodeProperties::GetControlInput(node, 0);
229 CHECK(!input->op()->HasProperty(Operator::kNoThrow));
230 // Type can be anything.
231 CheckUpperIs(node, Type::Any());
232 break;
233 }
234 case IrOpcode::kSwitch: {
235 // Switch uses are Case and Default.
236 int count_case = 0, count_default = 0;
Ben Murdochda12d292016-06-02 14:46:10 +0100237 for (const Node* use : node->uses()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 switch (use->opcode()) {
239 case IrOpcode::kIfValue: {
Ben Murdochda12d292016-06-02 14:46:10 +0100240 for (const Node* user : node->uses()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000241 if (user != use && user->opcode() == IrOpcode::kIfValue) {
242 CHECK_NE(OpParameter<int32_t>(use->op()),
243 OpParameter<int32_t>(user->op()));
244 }
245 }
246 ++count_case;
247 break;
248 }
249 case IrOpcode::kIfDefault: {
250 ++count_default;
251 break;
252 }
253 default: {
254 V8_Fatal(__FILE__, __LINE__, "Switch #%d illegally used by #%d:%s",
255 node->id(), use->id(), use->op()->mnemonic());
256 break;
257 }
258 }
259 }
260 CHECK_EQ(1, count_default);
261 CHECK_EQ(node->op()->ControlOutputCount(), count_case + count_default);
262 // Type is empty.
263 CheckNotTyped(node);
264 break;
265 }
266 case IrOpcode::kIfValue:
267 case IrOpcode::kIfDefault:
268 CHECK_EQ(IrOpcode::kSwitch,
269 NodeProperties::GetControlInput(node)->opcode());
270 // Type is empty.
271 CheckNotTyped(node);
272 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 case IrOpcode::kLoop:
274 case IrOpcode::kMerge:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400275 CHECK_EQ(control_count, input_count);
276 // Type is empty.
277 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100279 case IrOpcode::kDeoptimizeIf:
280 case IrOpcode::kDeoptimizeUnless:
281 // Type is empty.
282 CheckNotTyped(node);
283 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284 case IrOpcode::kDeoptimize:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 case IrOpcode::kReturn:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 case IrOpcode::kThrow:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287 // Deoptimize, Return and Throw uses are End.
Ben Murdochda12d292016-06-02 14:46:10 +0100288 for (const Node* use : node->uses()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 CHECK_EQ(IrOpcode::kEnd, use->opcode());
290 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400291 // Type is empty.
292 CheckNotTyped(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400294 case IrOpcode::kTerminate:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 // Terminates take one loop and effect.
296 CHECK_EQ(1, control_count);
297 CHECK_EQ(1, effect_count);
298 CHECK_EQ(2, input_count);
299 CHECK_EQ(IrOpcode::kLoop,
300 NodeProperties::GetControlInput(node)->opcode());
301 // Terminate uses are End.
Ben Murdochda12d292016-06-02 14:46:10 +0100302 for (const Node* use : node->uses()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000303 CHECK_EQ(IrOpcode::kEnd, use->opcode());
304 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400305 // Type is empty.
306 CheckNotTyped(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000307 break;
308 case IrOpcode::kOsrNormalEntry:
309 case IrOpcode::kOsrLoopEntry:
310 // Osr entries take one control and effect.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400311 CHECK_EQ(1, control_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000312 CHECK_EQ(1, effect_count);
313 CHECK_EQ(2, input_count);
314 // Type is empty.
315 CheckNotTyped(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400316 break;
317
318 // Common operators
319 // ----------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 case IrOpcode::kParameter: {
321 // Parameters have the start node as inputs.
322 CHECK_EQ(1, input_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 // Parameter has an input that produces enough values.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 int const index = ParameterIndexOf(node->op());
325 Node* const start = NodeProperties::GetValueInput(node, 0);
326 CHECK_EQ(IrOpcode::kStart, start->opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000327 // Currently, parameter indices start at -1 instead of 0.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328 CHECK_LE(-1, index);
329 CHECK_LT(index + 1, start->op()->ValueOutputCount());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400330 // Type can be anything.
331 CheckUpperIs(node, Type::Any());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 break;
333 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400334 case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant?
335 // Constants have no inputs.
336 CHECK_EQ(0, input_count);
337 // Type is a 32 bit integer, signed or unsigned.
338 CheckUpperIs(node, Type::Integral32());
339 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000340 case IrOpcode::kInt64Constant:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400341 // Constants have no inputs.
342 CHECK_EQ(0, input_count);
343 // Type is internal.
344 // TODO(rossberg): Introduce proper Int64 type.
345 CheckUpperIs(node, Type::Internal());
346 break;
347 case IrOpcode::kFloat32Constant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 case IrOpcode::kFloat64Constant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000349 case IrOpcode::kNumberConstant:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400350 // Constants have no inputs.
351 CHECK_EQ(0, input_count);
352 // Type is a number.
353 CheckUpperIs(node, Type::Number());
354 break;
Ben Murdochc5610432016-08-08 18:44:38 +0100355 case IrOpcode::kRelocatableInt32Constant:
356 case IrOpcode::kRelocatableInt64Constant:
357 CHECK_EQ(0, input_count);
358 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359 case IrOpcode::kHeapConstant:
360 // Constants have no inputs.
361 CHECK_EQ(0, input_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400362 // Type can be anything represented as a heap pointer.
363 CheckUpperIs(node, Type::TaggedPointer());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400365 case IrOpcode::kExternalConstant:
366 // Constants have no inputs.
367 CHECK_EQ(0, input_count);
368 // Type is considered internal.
369 CheckUpperIs(node, Type::Internal());
370 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371 case IrOpcode::kOsrValue:
372 // OSR values have a value and a control input.
373 CHECK_EQ(1, control_count);
374 CHECK_EQ(1, input_count);
375 // Type is merged from other values in the graph and could be any.
376 CheckUpperIs(node, Type::Any());
377 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400378 case IrOpcode::kProjection: {
379 // Projection has an input that produces enough values.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000380 int index = static_cast<int>(ProjectionIndexOf(node->op()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400381 Node* input = NodeProperties::GetValueInput(node, 0);
382 CHECK_GT(input->op()->ValueOutputCount(), index);
383 // Type can be anything.
384 // TODO(rossberg): Introduce tuple types for this.
385 // TODO(titzer): Convince rossberg not to.
386 CheckUpperIs(node, Type::Any());
387 break;
388 }
389 case IrOpcode::kSelect: {
390 CHECK_EQ(0, effect_count);
391 CHECK_EQ(0, control_count);
392 CHECK_EQ(3, value_count);
393 break;
394 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 case IrOpcode::kPhi: {
396 // Phi input count matches parent control node.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400397 CHECK_EQ(0, effect_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398 CHECK_EQ(1, control_count);
399 Node* control = NodeProperties::GetControlInput(node, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400400 CHECK_EQ(value_count, control->op()->ControlInputCount());
401 CHECK_EQ(input_count, 1 + value_count);
402 // Type must be subsumed by all input types.
403 // TODO(rossberg): for now at least, narrowing does not really hold.
404 /*
405 for (int i = 0; i < value_count; ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406 CHECK(type_of(ValueInput(node, i))->Is(type_of(node)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400407 }
408 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000409 break;
410 }
411 case IrOpcode::kEffectPhi: {
412 // EffectPhi input count matches parent control node.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400413 CHECK_EQ(0, value_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000414 CHECK_EQ(1, control_count);
415 Node* control = NodeProperties::GetControlInput(node, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400416 CHECK_EQ(effect_count, control->op()->ControlInputCount());
417 CHECK_EQ(input_count, 1 + effect_count);
418 break;
419 }
Ben Murdochc5610432016-08-08 18:44:38 +0100420 case IrOpcode::kTypeGuard:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421 // TODO(bmeurer): what are the constraints on these?
422 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100423 case IrOpcode::kCheckpoint:
Ben Murdochc5610432016-08-08 18:44:38 +0100424 // Type is empty.
425 CheckNotTyped(node);
426 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000427 case IrOpcode::kBeginRegion:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400428 // TODO(rossberg): what are the constraints on these?
429 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 case IrOpcode::kFinishRegion: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400431 // TODO(rossberg): what are the constraints on these?
432 // Type must be subsumed by input type.
433 if (typing == TYPED) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 Node* val = NodeProperties::GetValueInput(node, 0);
435 CHECK(NodeProperties::GetType(val)->Is(NodeProperties::GetType(node)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400436 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000437 break;
438 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100439 case IrOpcode::kFrameState: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440 // TODO(jarin): what are the constraints on these?
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 CHECK_EQ(5, value_count);
442 CHECK_EQ(0, control_count);
443 CHECK_EQ(0, effect_count);
444 CHECK_EQ(6, input_count);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100445 for (int i = 0; i < 3; ++i) {
446 CHECK(NodeProperties::GetValueInput(node, i)->opcode() ==
447 IrOpcode::kStateValues ||
448 NodeProperties::GetValueInput(node, i)->opcode() ==
449 IrOpcode::kTypedStateValues);
450 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100452 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400453 case IrOpcode::kStateValues:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454 case IrOpcode::kObjectState:
455 case IrOpcode::kTypedStateValues:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400456 // TODO(jarin): what are the constraints on these?
457 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000458 case IrOpcode::kCall:
459 // TODO(rossberg): what are the constraints on these?
460 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461 case IrOpcode::kTailCall:
462 // TODO(bmeurer): what are the constraints on these?
463 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400464
465 // JavaScript operators
466 // --------------------
467 case IrOpcode::kJSEqual:
468 case IrOpcode::kJSNotEqual:
469 case IrOpcode::kJSStrictEqual:
470 case IrOpcode::kJSStrictNotEqual:
471 case IrOpcode::kJSLessThan:
472 case IrOpcode::kJSGreaterThan:
473 case IrOpcode::kJSLessThanOrEqual:
474 case IrOpcode::kJSGreaterThanOrEqual:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400475 // Type is Boolean.
476 CheckUpperIs(node, Type::Boolean());
477 break;
478
479 case IrOpcode::kJSBitwiseOr:
480 case IrOpcode::kJSBitwiseXor:
481 case IrOpcode::kJSBitwiseAnd:
482 case IrOpcode::kJSShiftLeft:
483 case IrOpcode::kJSShiftRight:
484 case IrOpcode::kJSShiftRightLogical:
485 // Type is 32 bit integral.
486 CheckUpperIs(node, Type::Integral32());
487 break;
488 case IrOpcode::kJSAdd:
489 // Type is Number or String.
490 CheckUpperIs(node, Type::NumberOrString());
491 break;
492 case IrOpcode::kJSSubtract:
493 case IrOpcode::kJSMultiply:
494 case IrOpcode::kJSDivide:
495 case IrOpcode::kJSModulus:
496 // Type is Number.
497 CheckUpperIs(node, Type::Number());
498 break;
499
500 case IrOpcode::kJSToBoolean:
501 // Type is Boolean.
502 CheckUpperIs(node, Type::Boolean());
503 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100504 case IrOpcode::kJSToInteger:
505 // Type is OrderedNumber.
506 CheckUpperIs(node, Type::OrderedNumber());
507 break;
508 case IrOpcode::kJSToLength:
509 // Type is OrderedNumber.
510 CheckUpperIs(node, Type::OrderedNumber());
511 break;
512 case IrOpcode::kJSToName:
513 // Type is Name.
514 CheckUpperIs(node, Type::Name());
515 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400516 case IrOpcode::kJSToNumber:
517 // Type is Number.
518 CheckUpperIs(node, Type::Number());
519 break;
520 case IrOpcode::kJSToString:
521 // Type is String.
522 CheckUpperIs(node, Type::String());
523 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400524 case IrOpcode::kJSToObject:
525 // Type is Receiver.
526 CheckUpperIs(node, Type::Receiver());
527 break;
528
529 case IrOpcode::kJSCreate:
530 // Type is Object.
531 CheckUpperIs(node, Type::Object());
532 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000533 case IrOpcode::kJSCreateArguments:
534 // Type is OtherObject.
535 CheckUpperIs(node, Type::OtherObject());
536 break;
537 case IrOpcode::kJSCreateArray:
538 // Type is OtherObject.
539 CheckUpperIs(node, Type::OtherObject());
540 break;
541 case IrOpcode::kJSCreateClosure:
542 // Type is Function.
543 CheckUpperIs(node, Type::Function());
544 break;
545 case IrOpcode::kJSCreateIterResultObject:
546 // Type is OtherObject.
547 CheckUpperIs(node, Type::OtherObject());
548 break;
549 case IrOpcode::kJSCreateLiteralArray:
550 case IrOpcode::kJSCreateLiteralObject:
551 case IrOpcode::kJSCreateLiteralRegExp:
552 // Type is OtherObject.
553 CheckUpperIs(node, Type::OtherObject());
554 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400555 case IrOpcode::kJSLoadProperty:
556 case IrOpcode::kJSLoadNamed:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557 case IrOpcode::kJSLoadGlobal:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400558 // Type can be anything.
559 CheckUpperIs(node, Type::Any());
560 break;
561 case IrOpcode::kJSStoreProperty:
562 case IrOpcode::kJSStoreNamed:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 case IrOpcode::kJSStoreGlobal:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400564 // Type is empty.
565 CheckNotTyped(node);
566 break;
567 case IrOpcode::kJSDeleteProperty:
568 case IrOpcode::kJSHasProperty:
569 case IrOpcode::kJSInstanceOf:
570 // Type is Boolean.
571 CheckUpperIs(node, Type::Boolean());
572 break;
573 case IrOpcode::kJSTypeOf:
574 // Type is String.
575 CheckUpperIs(node, Type::String());
576 break;
577
578 case IrOpcode::kJSLoadContext:
579 // Type can be anything.
580 CheckUpperIs(node, Type::Any());
581 break;
582 case IrOpcode::kJSStoreContext:
583 // Type is empty.
584 CheckNotTyped(node);
585 break;
586 case IrOpcode::kJSCreateFunctionContext:
587 case IrOpcode::kJSCreateCatchContext:
588 case IrOpcode::kJSCreateWithContext:
589 case IrOpcode::kJSCreateBlockContext:
590 case IrOpcode::kJSCreateModuleContext:
591 case IrOpcode::kJSCreateScriptContext: {
592 // Type is Context, and operand is Internal.
593 Node* context = NodeProperties::GetContextInput(node);
594 // TODO(rossberg): This should really be Is(Internal), but the typer
595 // currently can't do backwards propagation.
596 CheckUpperMaybe(context, Type::Internal());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000597 if (typing == TYPED) CHECK(NodeProperties::GetType(node)->IsContext());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000598 break;
599 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400600
601 case IrOpcode::kJSCallConstruct:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 case IrOpcode::kJSConvertReceiver:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400603 // Type is Receiver.
604 CheckUpperIs(node, Type::Receiver());
605 break;
606 case IrOpcode::kJSCallFunction:
607 case IrOpcode::kJSCallRuntime:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608 // Type can be anything.
609 CheckUpperIs(node, Type::Any());
610 break;
611
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 case IrOpcode::kJSForInPrepare: {
613 // TODO(bmeurer): What are the constraints on thse?
614 CheckUpperIs(node, Type::Any());
615 break;
616 }
617 case IrOpcode::kJSForInDone: {
618 // TODO(bmeurer): OSR breaks this invariant, although the node is not user
619 // visible, so we know it is safe (fullcodegen has an unsigned smi there).
620 // CheckValueInputIs(node, 0, Type::UnsignedSmall());
621 break;
622 }
623 case IrOpcode::kJSForInNext: {
624 CheckUpperIs(node, Type::Union(Type::Name(), Type::Undefined(), zone));
625 break;
626 }
627 case IrOpcode::kJSForInStep: {
628 // TODO(bmeurer): OSR breaks this invariant, although the node is not user
629 // visible, so we know it is safe (fullcodegen has an unsigned smi there).
630 // CheckValueInputIs(node, 0, Type::UnsignedSmall());
631 CheckUpperIs(node, Type::UnsignedSmall());
632 break;
633 }
634
635 case IrOpcode::kJSLoadMessage:
636 case IrOpcode::kJSStoreMessage:
637 break;
638
Ben Murdoch61f157c2016-09-16 13:49:30 +0100639 case IrOpcode::kJSGeneratorStore:
640 CheckNotTyped(node);
641 break;
642
643 case IrOpcode::kJSGeneratorRestoreContinuation:
644 CheckUpperIs(node, Type::SignedSmall());
645 break;
646
647 case IrOpcode::kJSGeneratorRestoreRegister:
648 CheckUpperIs(node, Type::Any());
649 break;
650
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000651 case IrOpcode::kJSStackCheck:
652 // Type is empty.
653 CheckNotTyped(node);
654 break;
655
Ben Murdoch61f157c2016-09-16 13:49:30 +0100656 case IrOpcode::kDebugBreak:
657 CheckNotTyped(node);
658 break;
659
660 case IrOpcode::kComment:
661 CheckNotTyped(node);
662 break;
663
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400664 // Simplified operators
665 // -------------------------------
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400666 case IrOpcode::kBooleanNot:
667 // Boolean -> Boolean
668 CheckValueInputIs(node, 0, Type::Boolean());
669 CheckUpperIs(node, Type::Boolean());
670 break;
671 case IrOpcode::kBooleanToNumber:
672 // Boolean -> Number
673 CheckValueInputIs(node, 0, Type::Boolean());
674 CheckUpperIs(node, Type::Number());
675 break;
676 case IrOpcode::kNumberEqual:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100677 // (Number, Number) -> Boolean
678 CheckValueInputIs(node, 0, Type::Number());
679 CheckValueInputIs(node, 1, Type::Number());
Ben Murdochc5610432016-08-08 18:44:38 +0100680 CheckUpperIs(node, Type::Boolean());
681 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400682 case IrOpcode::kNumberLessThan:
683 case IrOpcode::kNumberLessThanOrEqual:
684 // (Number, Number) -> Boolean
Ben Murdoch61f157c2016-09-16 13:49:30 +0100685 CheckValueInputIs(node, 0, Type::Number());
686 CheckValueInputIs(node, 1, Type::Number());
687 CheckUpperIs(node, Type::Boolean());
688 break;
689 case IrOpcode::kSpeculativeNumberAdd:
690 case IrOpcode::kSpeculativeNumberSubtract:
691 case IrOpcode::kSpeculativeNumberMultiply:
692 case IrOpcode::kSpeculativeNumberDivide:
693 case IrOpcode::kSpeculativeNumberModulus:
694 CheckUpperIs(node, Type::Number());
695 break;
696 case IrOpcode::kSpeculativeNumberEqual:
697 case IrOpcode::kSpeculativeNumberLessThan:
698 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400699 CheckUpperIs(node, Type::Boolean());
700 break;
701 case IrOpcode::kNumberAdd:
702 case IrOpcode::kNumberSubtract:
703 case IrOpcode::kNumberMultiply:
704 case IrOpcode::kNumberDivide:
Ben Murdochc5610432016-08-08 18:44:38 +0100705 // (Number, Number) -> Number
Ben Murdoch61f157c2016-09-16 13:49:30 +0100706 CheckValueInputIs(node, 0, Type::Number());
707 CheckValueInputIs(node, 1, Type::Number());
708 CheckUpperIs(node, Type::Number());
Ben Murdochc5610432016-08-08 18:44:38 +0100709 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400710 case IrOpcode::kNumberModulus:
711 // (Number, Number) -> Number
712 CheckValueInputIs(node, 0, Type::Number());
713 CheckValueInputIs(node, 1, Type::Number());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100714 CheckUpperIs(node, Type::Number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400715 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 case IrOpcode::kNumberBitwiseOr:
717 case IrOpcode::kNumberBitwiseXor:
718 case IrOpcode::kNumberBitwiseAnd:
719 // (Signed32, Signed32) -> Signed32
720 CheckValueInputIs(node, 0, Type::Signed32());
721 CheckValueInputIs(node, 1, Type::Signed32());
722 CheckUpperIs(node, Type::Signed32());
723 break;
724 case IrOpcode::kNumberShiftLeft:
725 case IrOpcode::kNumberShiftRight:
726 // (Signed32, Unsigned32) -> Signed32
727 CheckValueInputIs(node, 0, Type::Signed32());
728 CheckValueInputIs(node, 1, Type::Unsigned32());
729 CheckUpperIs(node, Type::Signed32());
730 break;
731 case IrOpcode::kNumberShiftRightLogical:
732 // (Unsigned32, Unsigned32) -> Unsigned32
733 CheckValueInputIs(node, 0, Type::Unsigned32());
734 CheckValueInputIs(node, 1, Type::Unsigned32());
735 CheckUpperIs(node, Type::Unsigned32());
736 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100737 case IrOpcode::kNumberImul:
738 // (Unsigned32, Unsigned32) -> Signed32
739 CheckValueInputIs(node, 0, Type::Unsigned32());
740 CheckValueInputIs(node, 1, Type::Unsigned32());
741 CheckUpperIs(node, Type::Signed32());
742 break;
743 case IrOpcode::kNumberClz32:
744 // Unsigned32 -> Unsigned32
745 CheckValueInputIs(node, 0, Type::Unsigned32());
746 CheckUpperIs(node, Type::Unsigned32());
747 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100748 case IrOpcode::kNumberAtan2:
749 // (Number, Number) -> Number
750 CheckValueInputIs(node, 0, Type::Number());
751 CheckValueInputIs(node, 1, Type::Number());
752 CheckUpperIs(node, Type::Number());
753 break;
754 case IrOpcode::kNumberAbs:
Ben Murdochda12d292016-06-02 14:46:10 +0100755 case IrOpcode::kNumberCeil:
756 case IrOpcode::kNumberFloor:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100757 case IrOpcode::kNumberFround:
758 case IrOpcode::kNumberAtan:
759 case IrOpcode::kNumberAtanh:
760 case IrOpcode::kNumberCos:
761 case IrOpcode::kNumberExp:
762 case IrOpcode::kNumberExpm1:
763 case IrOpcode::kNumberLog:
764 case IrOpcode::kNumberLog1p:
765 case IrOpcode::kNumberLog2:
766 case IrOpcode::kNumberLog10:
767 case IrOpcode::kNumberCbrt:
Ben Murdochda12d292016-06-02 14:46:10 +0100768 case IrOpcode::kNumberRound:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100769 case IrOpcode::kNumberSin:
770 case IrOpcode::kNumberSqrt:
771 case IrOpcode::kNumberTan:
Ben Murdochda12d292016-06-02 14:46:10 +0100772 case IrOpcode::kNumberTrunc:
773 // Number -> Number
774 CheckValueInputIs(node, 0, Type::Number());
775 CheckUpperIs(node, Type::Number());
776 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400777 case IrOpcode::kNumberToInt32:
778 // Number -> Signed32
Ben Murdoch61f157c2016-09-16 13:49:30 +0100779 CheckValueInputIs(node, 0, Type::Number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400780 CheckUpperIs(node, Type::Signed32());
781 break;
782 case IrOpcode::kNumberToUint32:
783 // Number -> Unsigned32
Ben Murdoch61f157c2016-09-16 13:49:30 +0100784 CheckValueInputIs(node, 0, Type::Number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400785 CheckUpperIs(node, Type::Unsigned32());
786 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100787 case IrOpcode::kPlainPrimitiveToNumber:
788 // Type is Number.
789 CheckUpperIs(node, Type::Number());
790 break;
791 case IrOpcode::kPlainPrimitiveToWord32:
792 CheckUpperIs(node, Type::Number());
793 break;
794 case IrOpcode::kPlainPrimitiveToFloat64:
795 CheckUpperIs(node, Type::Number());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000796 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400797 case IrOpcode::kStringEqual:
798 case IrOpcode::kStringLessThan:
799 case IrOpcode::kStringLessThanOrEqual:
800 // (String, String) -> Boolean
801 CheckValueInputIs(node, 0, Type::String());
802 CheckValueInputIs(node, 1, Type::String());
803 CheckUpperIs(node, Type::Boolean());
804 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100805 case IrOpcode::kStringFromCharCode:
806 // Number -> String
807 CheckValueInputIs(node, 0, Type::Number());
808 CheckUpperIs(node, Type::String());
809 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100810 case IrOpcode::kStringToNumber:
811 // String -> Number
812 CheckValueInputIs(node, 0, Type::String());
813 CheckUpperIs(node, Type::Number());
814 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400815 case IrOpcode::kReferenceEqual: {
816 // (Unique, Any) -> Boolean and
817 // (Any, Unique) -> Boolean
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400818 CheckUpperIs(node, Type::Boolean());
819 break;
820 }
Ben Murdochc5610432016-08-08 18:44:38 +0100821 case IrOpcode::kObjectIsCallable:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000822 case IrOpcode::kObjectIsNumber:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100823 case IrOpcode::kObjectIsReceiver:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400824 case IrOpcode::kObjectIsSmi:
Ben Murdochc5610432016-08-08 18:44:38 +0100825 case IrOpcode::kObjectIsString:
Ben Murdochda12d292016-06-02 14:46:10 +0100826 case IrOpcode::kObjectIsUndetectable:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400827 CheckValueInputIs(node, 0, Type::Any());
828 CheckUpperIs(node, Type::Boolean());
829 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830 case IrOpcode::kAllocate:
831 CheckValueInputIs(node, 0, Type::PlainNumber());
832 CheckUpperIs(node, Type::TaggedPointer());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400833 break;
834
Ben Murdochc5610432016-08-08 18:44:38 +0100835 case IrOpcode::kChangeTaggedSignedToInt32: {
836 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
837 // TODO(neis): Activate once ChangeRepresentation works in typer.
838 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
839 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
840 // CheckValueInputIs(node, 0, from));
841 // CheckUpperIs(node, to));
842 break;
843 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400844 case IrOpcode::kChangeTaggedToInt32: {
845 // Signed32 /\ Tagged -> Signed32 /\ UntaggedInt32
846 // TODO(neis): Activate once ChangeRepresentation works in typer.
847 // Type* from = Type::Intersect(Type::Signed32(), Type::Tagged());
848 // Type* to = Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
849 // CheckValueInputIs(node, 0, from));
850 // CheckUpperIs(node, to));
851 break;
852 }
853 case IrOpcode::kChangeTaggedToUint32: {
854 // Unsigned32 /\ Tagged -> Unsigned32 /\ UntaggedInt32
855 // TODO(neis): Activate once ChangeRepresentation works in typer.
856 // Type* from = Type::Intersect(Type::Unsigned32(), Type::Tagged());
857 // Type* to =Type::Intersect(Type::Unsigned32(), Type::UntaggedInt32());
858 // CheckValueInputIs(node, 0, from));
859 // CheckUpperIs(node, to));
860 break;
861 }
862 case IrOpcode::kChangeTaggedToFloat64: {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100863 // NumberOrUndefined /\ Tagged -> Number /\ UntaggedFloat64
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400864 // TODO(neis): Activate once ChangeRepresentation works in typer.
865 // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
866 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
867 // CheckValueInputIs(node, 0, from));
868 // CheckUpperIs(node, to));
869 break;
870 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100871 case IrOpcode::kTruncateTaggedToFloat64: {
872 // NumberOrUndefined /\ Tagged -> Number /\ UntaggedFloat64
873 // TODO(neis): Activate once ChangeRepresentation works in typer.
874 // Type* from = Type::Intersect(Type::NumberOrUndefined(),
875 // Type::Tagged());
876 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedFloat64());
877 // CheckValueInputIs(node, 0, from));
878 // CheckUpperIs(node, to));
879 break;
880 }
Ben Murdochc5610432016-08-08 18:44:38 +0100881 case IrOpcode::kChangeInt31ToTaggedSigned: {
882 // Signed31 /\ UntaggedInt32 -> Signed31 /\ Tagged
883 // TODO(neis): Activate once ChangeRepresentation works in typer.
884 // Type* from =Type::Intersect(Type::Signed31(), Type::UntaggedInt32());
885 // Type* to = Type::Intersect(Type::Signed31(), Type::Tagged());
886 // CheckValueInputIs(node, 0, from));
887 // CheckUpperIs(node, to));
888 break;
889 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400890 case IrOpcode::kChangeInt32ToTagged: {
891 // Signed32 /\ UntaggedInt32 -> Signed32 /\ Tagged
892 // TODO(neis): Activate once ChangeRepresentation works in typer.
893 // Type* from =Type::Intersect(Type::Signed32(), Type::UntaggedInt32());
894 // Type* to = Type::Intersect(Type::Signed32(), Type::Tagged());
895 // CheckValueInputIs(node, 0, from));
896 // CheckUpperIs(node, to));
897 break;
898 }
899 case IrOpcode::kChangeUint32ToTagged: {
900 // Unsigned32 /\ UntaggedInt32 -> Unsigned32 /\ Tagged
901 // TODO(neis): Activate once ChangeRepresentation works in typer.
902 // Type* from=Type::Intersect(Type::Unsigned32(),Type::UntaggedInt32());
903 // Type* to = Type::Intersect(Type::Unsigned32(), Type::Tagged());
904 // CheckValueInputIs(node, 0, from));
905 // CheckUpperIs(node, to));
906 break;
907 }
908 case IrOpcode::kChangeFloat64ToTagged: {
909 // Number /\ UntaggedFloat64 -> Number /\ Tagged
910 // TODO(neis): Activate once ChangeRepresentation works in typer.
911 // Type* from =Type::Intersect(Type::Number(), Type::UntaggedFloat64());
912 // Type* to = Type::Intersect(Type::Number(), Type::Tagged());
913 // CheckValueInputIs(node, 0, from));
914 // CheckUpperIs(node, to));
915 break;
916 }
Ben Murdochc5610432016-08-08 18:44:38 +0100917 case IrOpcode::kChangeTaggedToBit: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400918 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
919 // TODO(neis): Activate once ChangeRepresentation works in typer.
920 // Type* from = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
921 // Type* to = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
922 // CheckValueInputIs(node, 0, from));
923 // CheckUpperIs(node, to));
924 break;
925 }
Ben Murdochc5610432016-08-08 18:44:38 +0100926 case IrOpcode::kChangeBitToTagged: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400927 // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
928 // TODO(neis): Activate once ChangeRepresentation works in typer.
929 // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
930 // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
931 // CheckValueInputIs(node, 0, from));
932 // CheckUpperIs(node, to));
933 break;
934 }
Ben Murdochc5610432016-08-08 18:44:38 +0100935 case IrOpcode::kTruncateTaggedToWord32: {
936 // Number /\ Tagged -> Signed32 /\ UntaggedInt32
937 // TODO(neis): Activate once ChangeRepresentation works in typer.
938 // Type* from = Type::Intersect(Type::Number(), Type::Tagged());
939 // Type* to = Type::Intersect(Type::Number(), Type::UntaggedInt32());
940 // CheckValueInputIs(node, 0, from));
941 // CheckUpperIs(node, to));
942 break;
943 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400944
Ben Murdoch61f157c2016-09-16 13:49:30 +0100945 case IrOpcode::kCheckBounds:
946 CheckValueInputIs(node, 0, Type::Any());
947 CheckValueInputIs(node, 1, Type::Unsigned31());
948 CheckUpperIs(node, Type::Unsigned31());
949 break;
950 case IrOpcode::kCheckTaggedSigned:
951 CheckValueInputIs(node, 0, Type::Any());
952 CheckUpperIs(node, Type::TaggedSigned());
953 break;
954 case IrOpcode::kCheckTaggedPointer:
955 CheckValueInputIs(node, 0, Type::Any());
956 CheckUpperIs(node, Type::TaggedPointer());
957 break;
958
959 case IrOpcode::kCheckedInt32Add:
960 case IrOpcode::kCheckedInt32Sub:
961 case IrOpcode::kCheckedUint32ToInt32:
962 case IrOpcode::kCheckedFloat64ToInt32:
963 case IrOpcode::kCheckedTaggedToInt32:
964 case IrOpcode::kCheckedTaggedToFloat64:
965 break;
966
967 case IrOpcode::kCheckFloat64Hole:
968 CheckValueInputIs(node, 0, Type::Number());
969 CheckUpperIs(node, Type::Number());
970 break;
971 case IrOpcode::kCheckTaggedHole:
972 CheckValueInputIs(node, 0, Type::Any());
973 CheckUpperIs(node, Type::Any());
974 break;
975
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400976 case IrOpcode::kLoadField:
977 // Object -> fieldtype
978 // TODO(rossberg): activate once machine ops are typed.
979 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980 // CheckUpperIs(node, FieldAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400981 break;
982 case IrOpcode::kLoadBuffer:
983 break;
984 case IrOpcode::kLoadElement:
985 // Object -> elementtype
986 // TODO(rossberg): activate once machine ops are typed.
987 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000988 // CheckUpperIs(node, ElementAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400989 break;
990 case IrOpcode::kStoreField:
991 // (Object, fieldtype) -> _|_
992 // TODO(rossberg): activate once machine ops are typed.
993 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000994 // CheckValueInputIs(node, 1, FieldAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400995 CheckNotTyped(node);
996 break;
997 case IrOpcode::kStoreBuffer:
998 break;
999 case IrOpcode::kStoreElement:
1000 // (Object, elementtype) -> _|_
1001 // TODO(rossberg): activate once machine ops are typed.
1002 // CheckValueInputIs(node, 0, Type::Object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001003 // CheckValueInputIs(node, 1, ElementAccessOf(node->op()).type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001004 CheckNotTyped(node);
1005 break;
Ben Murdoch61f157c2016-09-16 13:49:30 +01001006 case IrOpcode::kNumberSilenceNaN:
1007 CheckValueInputIs(node, 0, Type::Number());
1008 CheckUpperIs(node, Type::Number());
1009 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001010
1011 // Machine operators
1012 // -----------------------
1013 case IrOpcode::kLoad:
1014 case IrOpcode::kStore:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001015 case IrOpcode::kStackSlot:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001016 case IrOpcode::kWord32And:
1017 case IrOpcode::kWord32Or:
1018 case IrOpcode::kWord32Xor:
1019 case IrOpcode::kWord32Shl:
1020 case IrOpcode::kWord32Shr:
1021 case IrOpcode::kWord32Sar:
1022 case IrOpcode::kWord32Ror:
1023 case IrOpcode::kWord32Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001024 case IrOpcode::kWord32Clz:
1025 case IrOpcode::kWord32Ctz:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001026 case IrOpcode::kWord32ReverseBits:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001027 case IrOpcode::kWord32Popcnt:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001028 case IrOpcode::kWord64And:
1029 case IrOpcode::kWord64Or:
1030 case IrOpcode::kWord64Xor:
1031 case IrOpcode::kWord64Shl:
1032 case IrOpcode::kWord64Shr:
1033 case IrOpcode::kWord64Sar:
1034 case IrOpcode::kWord64Ror:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001035 case IrOpcode::kWord64Clz:
1036 case IrOpcode::kWord64Popcnt:
1037 case IrOpcode::kWord64Ctz:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001038 case IrOpcode::kWord64ReverseBits:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001039 case IrOpcode::kWord64Equal:
1040 case IrOpcode::kInt32Add:
1041 case IrOpcode::kInt32AddWithOverflow:
1042 case IrOpcode::kInt32Sub:
1043 case IrOpcode::kInt32SubWithOverflow:
1044 case IrOpcode::kInt32Mul:
1045 case IrOpcode::kInt32MulHigh:
1046 case IrOpcode::kInt32Div:
1047 case IrOpcode::kInt32Mod:
1048 case IrOpcode::kInt32LessThan:
1049 case IrOpcode::kInt32LessThanOrEqual:
1050 case IrOpcode::kUint32Div:
1051 case IrOpcode::kUint32Mod:
1052 case IrOpcode::kUint32MulHigh:
1053 case IrOpcode::kUint32LessThan:
1054 case IrOpcode::kUint32LessThanOrEqual:
1055 case IrOpcode::kInt64Add:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001056 case IrOpcode::kInt64AddWithOverflow:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001057 case IrOpcode::kInt64Sub:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001058 case IrOpcode::kInt64SubWithOverflow:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001059 case IrOpcode::kInt64Mul:
1060 case IrOpcode::kInt64Div:
1061 case IrOpcode::kInt64Mod:
1062 case IrOpcode::kInt64LessThan:
1063 case IrOpcode::kInt64LessThanOrEqual:
1064 case IrOpcode::kUint64Div:
1065 case IrOpcode::kUint64Mod:
1066 case IrOpcode::kUint64LessThan:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001067 case IrOpcode::kUint64LessThanOrEqual:
1068 case IrOpcode::kFloat32Add:
1069 case IrOpcode::kFloat32Sub:
Ben Murdochc5610432016-08-08 18:44:38 +01001070 case IrOpcode::kFloat32SubPreserveNan:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001071 case IrOpcode::kFloat32Neg:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 case IrOpcode::kFloat32Mul:
1073 case IrOpcode::kFloat32Div:
1074 case IrOpcode::kFloat32Max:
1075 case IrOpcode::kFloat32Min:
1076 case IrOpcode::kFloat32Abs:
1077 case IrOpcode::kFloat32Sqrt:
1078 case IrOpcode::kFloat32Equal:
1079 case IrOpcode::kFloat32LessThan:
1080 case IrOpcode::kFloat32LessThanOrEqual:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001081 case IrOpcode::kFloat64Add:
1082 case IrOpcode::kFloat64Sub:
Ben Murdochc5610432016-08-08 18:44:38 +01001083 case IrOpcode::kFloat64SubPreserveNan:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001084 case IrOpcode::kFloat64Neg:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001085 case IrOpcode::kFloat64Mul:
1086 case IrOpcode::kFloat64Div:
1087 case IrOpcode::kFloat64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001088 case IrOpcode::kFloat64Max:
1089 case IrOpcode::kFloat64Min:
1090 case IrOpcode::kFloat64Abs:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001091 case IrOpcode::kFloat64Atan:
1092 case IrOpcode::kFloat64Atan2:
1093 case IrOpcode::kFloat64Atanh:
1094 case IrOpcode::kFloat64Cos:
1095 case IrOpcode::kFloat64Exp:
1096 case IrOpcode::kFloat64Expm1:
1097 case IrOpcode::kFloat64Log:
1098 case IrOpcode::kFloat64Log1p:
1099 case IrOpcode::kFloat64Log2:
1100 case IrOpcode::kFloat64Log10:
1101 case IrOpcode::kFloat64Cbrt:
1102 case IrOpcode::kFloat64Sin:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001103 case IrOpcode::kFloat64Sqrt:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001104 case IrOpcode::kFloat64Tan:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001105 case IrOpcode::kFloat32RoundDown:
1106 case IrOpcode::kFloat64RoundDown:
1107 case IrOpcode::kFloat32RoundUp:
1108 case IrOpcode::kFloat64RoundUp:
1109 case IrOpcode::kFloat32RoundTruncate:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001110 case IrOpcode::kFloat64RoundTruncate:
1111 case IrOpcode::kFloat64RoundTiesAway:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001112 case IrOpcode::kFloat32RoundTiesEven:
1113 case IrOpcode::kFloat64RoundTiesEven:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001114 case IrOpcode::kFloat64Equal:
1115 case IrOpcode::kFloat64LessThan:
1116 case IrOpcode::kFloat64LessThanOrEqual:
1117 case IrOpcode::kTruncateInt64ToInt32:
Ben Murdochc5610432016-08-08 18:44:38 +01001118 case IrOpcode::kRoundFloat64ToInt32:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001119 case IrOpcode::kRoundInt32ToFloat32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001120 case IrOpcode::kRoundInt64ToFloat32:
1121 case IrOpcode::kRoundInt64ToFloat64:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001122 case IrOpcode::kRoundUint32ToFloat32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001123 case IrOpcode::kRoundUint64ToFloat64:
1124 case IrOpcode::kRoundUint64ToFloat32:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001125 case IrOpcode::kTruncateFloat64ToFloat32:
Ben Murdochc5610432016-08-08 18:44:38 +01001126 case IrOpcode::kTruncateFloat64ToWord32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001127 case IrOpcode::kBitcastFloat32ToInt32:
1128 case IrOpcode::kBitcastFloat64ToInt64:
1129 case IrOpcode::kBitcastInt32ToFloat32:
1130 case IrOpcode::kBitcastInt64ToFloat64:
Ben Murdochc5610432016-08-08 18:44:38 +01001131 case IrOpcode::kBitcastWordToTagged:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001132 case IrOpcode::kChangeInt32ToInt64:
1133 case IrOpcode::kChangeUint32ToUint64:
1134 case IrOpcode::kChangeInt32ToFloat64:
1135 case IrOpcode::kChangeUint32ToFloat64:
1136 case IrOpcode::kChangeFloat32ToFloat64:
1137 case IrOpcode::kChangeFloat64ToInt32:
1138 case IrOpcode::kChangeFloat64ToUint32:
Ben Murdoch61f157c2016-09-16 13:49:30 +01001139 case IrOpcode::kFloat64SilenceNaN:
Ben Murdochda12d292016-06-02 14:46:10 +01001140 case IrOpcode::kTruncateFloat64ToUint32:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001141 case IrOpcode::kTruncateFloat32ToInt32:
1142 case IrOpcode::kTruncateFloat32ToUint32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001143 case IrOpcode::kTryTruncateFloat32ToInt64:
1144 case IrOpcode::kTryTruncateFloat64ToInt64:
1145 case IrOpcode::kTryTruncateFloat32ToUint64:
1146 case IrOpcode::kTryTruncateFloat64ToUint64:
1147 case IrOpcode::kFloat64ExtractLowWord32:
1148 case IrOpcode::kFloat64ExtractHighWord32:
1149 case IrOpcode::kFloat64InsertLowWord32:
1150 case IrOpcode::kFloat64InsertHighWord32:
Ben Murdochda12d292016-06-02 14:46:10 +01001151 case IrOpcode::kInt32PairAdd:
1152 case IrOpcode::kInt32PairSub:
1153 case IrOpcode::kInt32PairMul:
1154 case IrOpcode::kWord32PairShl:
1155 case IrOpcode::kWord32PairShr:
1156 case IrOpcode::kWord32PairSar:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001157 case IrOpcode::kLoadStackPointer:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001158 case IrOpcode::kLoadFramePointer:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001159 case IrOpcode::kLoadParentFramePointer:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001160 case IrOpcode::kCheckedLoad:
1161 case IrOpcode::kCheckedStore:
Ben Murdochc5610432016-08-08 18:44:38 +01001162 case IrOpcode::kAtomicLoad:
1163 case IrOpcode::kAtomicStore:
1164
1165#define SIMD_MACHINE_OP_CASE(Name) case IrOpcode::k##Name:
1166 MACHINE_SIMD_OP_LIST(SIMD_MACHINE_OP_CASE)
1167#undef SIMD_MACHINE_OP_CASE
1168
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001169 // TODO(rossberg): Check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001170 break;
1171 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001172} // NOLINT(readability/fn_size)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001173
Ben Murdochc5610432016-08-08 18:44:38 +01001174void Verifier::Run(Graph* graph, Typing typing, CheckInputs check_inputs) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001175 CHECK_NOT_NULL(graph->start());
1176 CHECK_NOT_NULL(graph->end());
Ben Murdochda12d292016-06-02 14:46:10 +01001177 Zone zone(graph->zone()->allocator());
Ben Murdochc5610432016-08-08 18:44:38 +01001178 Visitor visitor(&zone, typing, check_inputs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001179 AllNodes all(&zone, graph);
1180 for (Node* node : all.live) visitor.Check(node);
1181
1182 // Check the uniqueness of projections.
1183 for (Node* proj : all.live) {
1184 if (proj->opcode() != IrOpcode::kProjection) continue;
1185 Node* node = proj->InputAt(0);
1186 for (Node* other : node->uses()) {
1187 if (all.IsLive(other) && other != proj &&
1188 other->opcode() == IrOpcode::kProjection &&
1189 ProjectionIndexOf(other->op()) == ProjectionIndexOf(proj->op())) {
1190 V8_Fatal(__FILE__, __LINE__,
1191 "Node #%d:%s has duplicate projections #%d and #%d",
1192 node->id(), node->op()->mnemonic(), proj->id(), other->id());
1193 }
1194 }
1195 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001196}
1197
1198
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001199// -----------------------------------------------------------------------------
1200
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001201static bool HasDominatingDef(Schedule* schedule, Node* node,
1202 BasicBlock* container, BasicBlock* use_block,
1203 int use_pos) {
1204 BasicBlock* block = use_block;
1205 while (true) {
1206 while (use_pos >= 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001207 if (block->NodeAt(use_pos) == node) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001208 use_pos--;
1209 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001210 block = block->dominator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001211 if (block == nullptr) break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001212 use_pos = static_cast<int>(block->NodeCount()) - 1;
1213 if (node == block->control_input()) return true;
1214 }
1215 return false;
1216}
1217
1218
1219static bool Dominates(Schedule* schedule, Node* dominator, Node* dominatee) {
1220 BasicBlock* dom = schedule->block(dominator);
1221 BasicBlock* sub = schedule->block(dominatee);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001222 while (sub != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001223 if (sub == dom) {
1224 return true;
1225 }
1226 sub = sub->dominator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001227 }
1228 return false;
1229}
1230
1231
1232static void CheckInputsDominate(Schedule* schedule, BasicBlock* block,
1233 Node* node, int use_pos) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001234 for (int j = node->op()->ValueInputCount() - 1; j >= 0; j--) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001235 BasicBlock* use_block = block;
1236 if (node->opcode() == IrOpcode::kPhi) {
1237 use_block = use_block->PredecessorAt(j);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001238 use_pos = static_cast<int>(use_block->NodeCount()) - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001239 }
1240 Node* input = node->InputAt(j);
1241 if (!HasDominatingDef(schedule, node->InputAt(j), block, use_block,
1242 use_pos)) {
1243 V8_Fatal(__FILE__, __LINE__,
1244 "Node #%d:%s in B%d is not dominated by input@%d #%d:%s",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001245 node->id(), node->op()->mnemonic(), block->rpo_number(), j,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001246 input->id(), input->op()->mnemonic());
1247 }
1248 }
1249 // Ensure that nodes are dominated by their control inputs;
1250 // kEnd is an exception, as unreachable blocks resulting from kMerge
1251 // are not in the RPO.
1252 if (node->op()->ControlInputCount() == 1 &&
1253 node->opcode() != IrOpcode::kEnd) {
1254 Node* ctl = NodeProperties::GetControlInput(node);
1255 if (!Dominates(schedule, ctl, node)) {
1256 V8_Fatal(__FILE__, __LINE__,
1257 "Node #%d:%s in B%d is not dominated by control input #%d:%s",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001258 node->id(), node->op()->mnemonic(), block->rpo_number(),
1259 ctl->id(), ctl->op()->mnemonic());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001260 }
1261 }
1262}
1263
1264
1265void ScheduleVerifier::Run(Schedule* schedule) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001266 const size_t count = schedule->BasicBlockCount();
Ben Murdochda12d292016-06-02 14:46:10 +01001267 Zone tmp_zone(schedule->zone()->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001268 Zone* zone = &tmp_zone;
1269 BasicBlock* start = schedule->start();
1270 BasicBlockVector* rpo_order = schedule->rpo_order();
1271
1272 // Verify the RPO order contains only blocks from this schedule.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001273 CHECK_GE(count, rpo_order->size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001274 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
1275 ++b) {
1276 CHECK_EQ((*b), schedule->GetBlockById((*b)->id()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001277 // All predecessors and successors should be in rpo and in this schedule.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001278 for (BasicBlock const* predecessor : (*b)->predecessors()) {
1279 CHECK_GE(predecessor->rpo_number(), 0);
1280 CHECK_EQ(predecessor, schedule->GetBlockById(predecessor->id()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001281 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001282 for (BasicBlock const* successor : (*b)->successors()) {
1283 CHECK_GE(successor->rpo_number(), 0);
1284 CHECK_EQ(successor, schedule->GetBlockById(successor->id()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001285 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001286 }
1287
1288 // Verify RPO numbers of blocks.
1289 CHECK_EQ(start, rpo_order->at(0)); // Start should be first.
1290 for (size_t b = 0; b < rpo_order->size(); b++) {
1291 BasicBlock* block = rpo_order->at(b);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001292 CHECK_EQ(static_cast<int>(b), block->rpo_number());
1293 BasicBlock* dom = block->dominator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001294 if (b == 0) {
1295 // All blocks except start should have a dominator.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001296 CHECK_NULL(dom);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001297 } else {
1298 // Check that the immediate dominator appears somewhere before the block.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001299 CHECK_NOT_NULL(dom);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001300 CHECK_LT(dom->rpo_number(), block->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001301 }
1302 }
1303
1304 // Verify that all blocks reachable from start are in the RPO.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001305 BoolVector marked(static_cast<int>(count), false, zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001306 {
1307 ZoneQueue<BasicBlock*> queue(zone);
1308 queue.push(start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001309 marked[start->id().ToSize()] = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001310 while (!queue.empty()) {
1311 BasicBlock* block = queue.front();
1312 queue.pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001313 for (size_t s = 0; s < block->SuccessorCount(); s++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001314 BasicBlock* succ = block->SuccessorAt(s);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001315 if (!marked[succ->id().ToSize()]) {
1316 marked[succ->id().ToSize()] = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001317 queue.push(succ);
1318 }
1319 }
1320 }
1321 }
1322 // Verify marked blocks are in the RPO.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001323 for (size_t i = 0; i < count; i++) {
1324 BasicBlock* block = schedule->GetBlockById(BasicBlock::Id::FromSize(i));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001325 if (marked[i]) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001326 CHECK_GE(block->rpo_number(), 0);
1327 CHECK_EQ(block, rpo_order->at(block->rpo_number()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001328 }
1329 }
1330 // Verify RPO blocks are marked.
1331 for (size_t b = 0; b < rpo_order->size(); b++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001332 CHECK(marked[rpo_order->at(b)->id().ToSize()]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001333 }
1334
1335 {
1336 // Verify the dominance relation.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001337 ZoneVector<BitVector*> dominators(zone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001338 dominators.resize(count, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001339
1340 // Compute a set of all the nodes that dominate a given node by using
1341 // a forward fixpoint. O(n^2).
1342 ZoneQueue<BasicBlock*> queue(zone);
1343 queue.push(start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001344 dominators[start->id().ToSize()] =
1345 new (zone) BitVector(static_cast<int>(count), zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001346 while (!queue.empty()) {
1347 BasicBlock* block = queue.front();
1348 queue.pop();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001349 BitVector* block_doms = dominators[block->id().ToSize()];
1350 BasicBlock* idom = block->dominator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001351 if (idom != nullptr && !block_doms->Contains(idom->id().ToInt())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001352 V8_Fatal(__FILE__, __LINE__, "Block B%d is not dominated by B%d",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001353 block->rpo_number(), idom->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001354 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001355 for (size_t s = 0; s < block->SuccessorCount(); s++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356 BasicBlock* succ = block->SuccessorAt(s);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001357 BitVector* succ_doms = dominators[succ->id().ToSize()];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001358
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001359 if (succ_doms == nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001360 // First time visiting the node. S.doms = B U B.doms
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001361 succ_doms = new (zone) BitVector(static_cast<int>(count), zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001362 succ_doms->CopyFrom(*block_doms);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001363 succ_doms->Add(block->id().ToInt());
1364 dominators[succ->id().ToSize()] = succ_doms;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001365 queue.push(succ);
1366 } else {
1367 // Nth time visiting the successor. S.doms = S.doms ^ (B U B.doms)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001368 bool had = succ_doms->Contains(block->id().ToInt());
1369 if (had) succ_doms->Remove(block->id().ToInt());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001370 if (succ_doms->IntersectIsChanged(*block_doms)) queue.push(succ);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001371 if (had) succ_doms->Add(block->id().ToInt());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001372 }
1373 }
1374 }
1375
1376 // Verify the immediateness of dominators.
1377 for (BasicBlockVector::iterator b = rpo_order->begin();
1378 b != rpo_order->end(); ++b) {
1379 BasicBlock* block = *b;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001380 BasicBlock* idom = block->dominator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001381 if (idom == nullptr) continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001382 BitVector* block_doms = dominators[block->id().ToSize()];
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001383
1384 for (BitVector::Iterator it(block_doms); !it.Done(); it.Advance()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001385 BasicBlock* dom =
1386 schedule->GetBlockById(BasicBlock::Id::FromInt(it.Current()));
1387 if (dom != idom &&
1388 !dominators[idom->id().ToSize()]->Contains(dom->id().ToInt())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001389 V8_Fatal(__FILE__, __LINE__,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001390 "Block B%d is not immediately dominated by B%d",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001391 block->rpo_number(), idom->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392 }
1393 }
1394 }
1395 }
1396
1397 // Verify phis are placed in the block of their control input.
1398 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
1399 ++b) {
1400 for (BasicBlock::const_iterator i = (*b)->begin(); i != (*b)->end(); ++i) {
1401 Node* phi = *i;
1402 if (phi->opcode() != IrOpcode::kPhi) continue;
1403 // TODO(titzer): Nasty special case. Phis from RawMachineAssembler
1404 // schedules don't have control inputs.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001405 if (phi->InputCount() > phi->op()->ValueInputCount()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001406 Node* control = NodeProperties::GetControlInput(phi);
1407 CHECK(control->opcode() == IrOpcode::kMerge ||
1408 control->opcode() == IrOpcode::kLoop);
1409 CHECK_EQ((*b), schedule->block(control));
1410 }
1411 }
1412 }
1413
1414 // Verify that all uses are dominated by their definitions.
1415 for (BasicBlockVector::iterator b = rpo_order->begin(); b != rpo_order->end();
1416 ++b) {
1417 BasicBlock* block = *b;
1418
1419 // Check inputs to control for this block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001420 Node* control = block->control_input();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001421 if (control != nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001422 CHECK_EQ(block, schedule->block(control));
1423 CheckInputsDominate(schedule, block, control,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001424 static_cast<int>(block->NodeCount()) - 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001425 }
1426 // Check inputs for all nodes in the block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001427 for (size_t i = 0; i < block->NodeCount(); i++) {
1428 Node* node = block->NodeAt(i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001429 CheckInputsDominate(schedule, block, node, static_cast<int>(i) - 1);
1430 }
1431 }
1432}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001433
1434
1435#ifdef DEBUG
1436
1437// static
1438void Verifier::VerifyNode(Node* node) {
1439 CHECK_EQ(OperatorProperties::GetTotalInputCount(node->op()),
1440 node->InputCount());
1441 // If this node has no effect or no control outputs,
1442 // we check that no its uses are effect or control inputs.
1443 bool check_no_control = node->op()->ControlOutputCount() == 0;
1444 bool check_no_effect = node->op()->EffectOutputCount() == 0;
1445 bool check_no_frame_state = node->opcode() != IrOpcode::kFrameState;
1446 if (check_no_effect || check_no_control) {
1447 for (Edge edge : node->use_edges()) {
1448 Node* const user = edge.from();
1449 CHECK(!user->IsDead());
1450 if (NodeProperties::IsControlEdge(edge)) {
1451 CHECK(!check_no_control);
1452 } else if (NodeProperties::IsEffectEdge(edge)) {
1453 CHECK(!check_no_effect);
1454 } else if (NodeProperties::IsFrameStateEdge(edge)) {
1455 CHECK(!check_no_frame_state);
1456 }
1457 }
1458 }
1459 // Frame state inputs should be frame states (or sentinels).
1460 for (int i = 0; i < OperatorProperties::GetFrameStateInputCount(node->op());
1461 i++) {
1462 Node* input = NodeProperties::GetFrameStateInput(node, i);
1463 CHECK(input->opcode() == IrOpcode::kFrameState ||
1464 input->opcode() == IrOpcode::kStart ||
1465 input->opcode() == IrOpcode::kDead);
1466 }
1467 // Effect inputs should be effect-producing nodes (or sentinels).
1468 for (int i = 0; i < node->op()->EffectInputCount(); i++) {
1469 Node* input = NodeProperties::GetEffectInput(node, i);
1470 CHECK(input->op()->EffectOutputCount() > 0 ||
1471 input->opcode() == IrOpcode::kDead);
1472 }
1473 // Control inputs should be control-producing nodes (or sentinels).
1474 for (int i = 0; i < node->op()->ControlInputCount(); i++) {
1475 Node* input = NodeProperties::GetControlInput(node, i);
1476 CHECK(input->op()->ControlOutputCount() > 0 ||
1477 input->opcode() == IrOpcode::kDead);
1478 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001479}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001480
1481
1482void Verifier::VerifyEdgeInputReplacement(const Edge& edge,
1483 const Node* replacement) {
1484 // Check that the user does not misuse the replacement.
1485 DCHECK(!NodeProperties::IsControlEdge(edge) ||
1486 replacement->op()->ControlOutputCount() > 0);
1487 DCHECK(!NodeProperties::IsEffectEdge(edge) ||
1488 replacement->op()->EffectOutputCount() > 0);
1489 DCHECK(!NodeProperties::IsFrameStateEdge(edge) ||
1490 replacement->opcode() == IrOpcode::kFrameState);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001492
1493#endif // DEBUG
1494
1495} // namespace compiler
1496} // namespace internal
1497} // namespace v8