Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: src/compiler/js-typed-lowering.cc

Issue 426233002: Land the Fan (disabled) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review feedback, rebase and "git cl format" Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/linkage.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/graph-inl.h"
6 #include "src/compiler/js-typed-lowering.h"
7 #include "src/compiler/node-aux-data-inl.h"
8 #include "src/compiler/node-properties-inl.h"
9 #include "src/types.h"
10
11 namespace v8 {
12 namespace internal {
13 namespace compiler {
14
15 // TODO(turbofan): js-typed-lowering improvements possible
16 // - immediately put in type bounds for all new nodes
17 // - relax effects from generic but not-side-effecting operations
18 // - relax effects for ToNumber(mixed)
19
20 // Replace value uses of {node} with {value} and effect uses of {node} with
21 // {effect}. If {effect == NULL}, then use the effect input to {node}.
22 // TODO(titzer): move into a GraphEditor?
23 static void ReplaceUses(Node* node, Node* value, Node* effect) {
24 if (value == effect) {
25 // Effect and value updates are the same; no special iteration needed.
26 if (value != node) node->ReplaceUses(value);
27 return;
28 }
29
30 if (effect == NULL) effect = NodeProperties::GetEffectInput(node);
31
32 // The iteration requires distinguishing between value and effect edges.
33 UseIter iter = node->uses().begin();
34 while (iter != node->uses().end()) {
35 if (NodeProperties::IsEffectEdge(iter.edge())) {
36 iter = iter.UpdateToAndIncrement(effect);
37 } else {
38 iter = iter.UpdateToAndIncrement(value);
39 }
40 }
41 }
42
43
44 // Relax the effects of {node} by immediately replacing effect uses of {node}
45 // with the effect input to {node}.
46 // TODO(turbofan): replace the effect input to {node} with {graph->start()}.
47 // TODO(titzer): move into a GraphEditor?
48 static void RelaxEffects(Node* node) { ReplaceUses(node, node, NULL); }
49
50
51 Reduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) {
52 ReplaceUses(old, node, node);
53 return Reducer::Changed(node);
54 }
55
56
57 // A helper class to simplify the process of reducing a single binop node with a
58 // JSOperator. This class manages the rewriting of context, control, and effect
59 // dependencies during lowering of a binop and contains numerous helper
60 // functions for matching the types of inputs to an operation.
61 class JSBinopReduction {
62 public:
63 JSBinopReduction(JSTypedLowering* lowering, Node* node)
64 : lowering_(lowering),
65 node_(node),
66 left_type_(NodeProperties::GetBounds(node->InputAt(0)).upper),
67 right_type_(NodeProperties::GetBounds(node->InputAt(1)).upper) {}
68
69 void ConvertInputsToNumber() {
70 node_->ReplaceInput(0, ConvertToNumber(left()));
71 node_->ReplaceInput(1, ConvertToNumber(right()));
72 }
73
74 void ConvertInputsToInt32(bool left_signed, bool right_signed) {
75 node_->ReplaceInput(0, ConvertToI32(left_signed, left()));
76 node_->ReplaceInput(1, ConvertToI32(right_signed, right()));
77 }
78
79 void ConvertInputsToString() {
80 node_->ReplaceInput(0, ConvertToString(left()));
81 node_->ReplaceInput(1, ConvertToString(right()));
82 }
83
84 // Convert inputs for bitwise shift operation (ES5 spec 11.7).
85 void ConvertInputsForShift(bool left_signed) {
86 node_->ReplaceInput(0, ConvertToI32(left_signed, left()));
87 Node* rnum = ConvertToI32(false, right());
88 node_->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rnum,
89 jsgraph()->Int32Constant(0x1F)));
90 }
91
92 void SwapInputs() {
93 Node* l = left();
94 Node* r = right();
95 node_->ReplaceInput(0, r);
96 node_->ReplaceInput(1, l);
97 std::swap(left_type_, right_type_);
98 }
99
100 // Remove all effect and control inputs and outputs to this node and change
101 // to the pure operator {op}, possibly inserting a boolean inversion.
102 Reduction ChangeToPureOperator(Operator* op, bool invert = false) {
103 ASSERT_EQ(0, OperatorProperties::GetEffectInputCount(op));
104 ASSERT_EQ(false, OperatorProperties::HasContextInput(op));
105 ASSERT_EQ(0, OperatorProperties::GetControlInputCount(op));
106 ASSERT_EQ(2, OperatorProperties::GetValueInputCount(op));
107
108 // Remove the effects from the node, if any, and update its effect usages.
109 if (OperatorProperties::GetEffectInputCount(node_->op()) > 0) {
110 RelaxEffects(node_);
111 }
112 // Remove the inputs corresponding to context, effect, and control.
113 NodeProperties::RemoveNonValueInputs(node_);
114 // Finally, update the operator to the new one.
115 node_->set_op(op);
116
117 if (invert) {
118 // Insert an boolean not to invert the value.
119 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
120 node_->ReplaceUses(value);
121 // Note: ReplaceUses() smashes all uses, so smash it back here.
122 value->ReplaceInput(0, node_);
123 return lowering_->ReplaceWith(value);
124 }
125 return lowering_->Changed(node_);
126 }
127
128 bool OneInputIs(Type* t) { return left_type_->Is(t) || right_type_->Is(t); }
129
130 bool BothInputsAre(Type* t) {
131 return left_type_->Is(t) && right_type_->Is(t);
132 }
133
134 bool OneInputCannotBe(Type* t) {
135 return !left_type_->Maybe(t) || !right_type_->Maybe(t);
136 }
137
138 bool NeitherInputCanBe(Type* t) {
139 return !left_type_->Maybe(t) && !right_type_->Maybe(t);
140 }
141
142 Node* effect() { return NodeProperties::GetEffectInput(node_); }
143 Node* control() { return NodeProperties::GetControlInput(node_); }
144 Node* context() { return NodeProperties::GetContextInput(node_); }
145 Node* left() { return NodeProperties::GetValueInput(node_, 0); }
146 Node* right() { return NodeProperties::GetValueInput(node_, 1); }
147 Type* left_type() { return left_type_; }
148 Type* right_type() { return right_type_; }
149
150 SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); }
151 Graph* graph() { return lowering_->graph(); }
152 JSGraph* jsgraph() { return lowering_->jsgraph(); }
153 JSOperatorBuilder* javascript() { return lowering_->javascript(); }
154 MachineOperatorBuilder* machine() { return lowering_->machine(); }
155
156 private:
157 JSTypedLowering* lowering_; // The containing lowering instance.
158 Node* node_; // The original node.
159 Type* left_type_; // Cache of the left input's type.
160 Type* right_type_; // Cache of the right input's type.
161
162 Node* ConvertToString(Node* node) {
163 // Avoid introducing too many eager ToString() operations.
164 Reduction reduced = lowering_->ReduceJSToStringInput(node);
165 if (reduced.Changed()) return reduced.replacement();
166 Node* n = graph()->NewNode(javascript()->ToString(), node, context(),
167 effect(), control());
168 update_effect(n);
169 return n;
170 }
171
172 Node* ConvertToNumber(Node* node) {
173 // Avoid introducing too many eager ToNumber() operations.
174 Reduction reduced = lowering_->ReduceJSToNumberInput(node);
175 if (reduced.Changed()) return reduced.replacement();
176 Node* n = graph()->NewNode(javascript()->ToNumber(), node, context(),
177 effect(), control());
178 update_effect(n);
179 return n;
180 }
181
182 // Try to narrowing a double or number operation to an Int32 operation.
183 bool TryNarrowingToI32(Type* type, Node* node) {
184 switch (node->opcode()) {
185 case IrOpcode::kFloat64Add:
186 case IrOpcode::kNumberAdd: {
187 JSBinopReduction r(lowering_, node);
188 if (r.BothInputsAre(Type::Integral32())) {
189 node->set_op(lowering_->machine()->Int32Add());
190 // TODO(titzer): narrow bounds instead of overwriting.
191 NodeProperties::SetBounds(node, Bounds(type));
192 return true;
193 }
194 }
195 case IrOpcode::kFloat64Sub:
196 case IrOpcode::kNumberSubtract: {
197 JSBinopReduction r(lowering_, node);
198 if (r.BothInputsAre(Type::Integral32())) {
199 node->set_op(lowering_->machine()->Int32Sub());
200 // TODO(titzer): narrow bounds instead of overwriting.
201 NodeProperties::SetBounds(node, Bounds(type));
202 return true;
203 }
204 }
205 default:
206 return false;
207 }
208 }
209
210 Node* ConvertToI32(bool is_signed, Node* node) {
211 Type* type = is_signed ? Type::Signed32() : Type::Unsigned32();
212 if (node->OwnedBy(node_)) {
213 // If this node {node_} has the only edge to {node}, then try narrowing
214 // its operation to an Int32 add or subtract.
215 if (TryNarrowingToI32(type, node)) return node;
216 } else {
217 // Otherwise, {node} has multiple uses. Leave it as is and let the
218 // further lowering passes deal with it, which use a full backwards
219 // fixpoint.
220 }
221
222 // Avoid introducing too many eager NumberToXXnt32() operations.
223 node = ConvertToNumber(node);
224 Type* input_type = NodeProperties::GetBounds(node).upper;
225
226 if (input_type->Is(type)) return node; // already in the value range.
227
228 Operator* op = is_signed ? simplified()->NumberToInt32()
229 : simplified()->NumberToUint32();
230 Node* n = graph()->NewNode(op, node);
231 return n;
232 }
233
234 void update_effect(Node* effect) {
235 NodeProperties::ReplaceEffectInput(node_, effect);
236 }
237 };
238
239
240 Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
241 JSBinopReduction r(this, node);
242 if (r.OneInputIs(Type::String())) {
243 r.ConvertInputsToString();
244 return r.ChangeToPureOperator(simplified()->StringAdd());
245 } else if (r.NeitherInputCanBe(Type::String())) {
246 r.ConvertInputsToNumber();
247 return r.ChangeToPureOperator(simplified()->NumberAdd());
248 }
249 return NoChange();
250 }
251
252
253 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, Operator* numberOp) {
254 JSBinopReduction r(this, node);
255 if (r.OneInputIs(Type::Primitive())) {
256 // If at least one input is a primitive, then insert appropriate conversions
257 // to number and reduce this operator to the given numeric one.
258 // TODO(turbofan): make this heuristic configurable for code size.
259 r.ConvertInputsToNumber();
260 return r.ChangeToPureOperator(numberOp);
261 }
262 // TODO(turbofan): relax/remove the effects of this operator in other cases.
263 return NoChange();
264 }
265
266
267 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed,
268 bool right_signed, Operator* intOp) {
269 JSBinopReduction r(this, node);
270 // TODO(titzer): some Smi bitwise operations don't really require going
271 // all the way to int32, which can save tagging/untagging for some operations
272 // on some platforms.
273 // TODO(turbofan): make this heuristic configurable for code size.
274 r.ConvertInputsToInt32(left_signed, right_signed);
275 return r.ChangeToPureOperator(intOp);
276 }
277
278
279 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed,
280 Operator* shift_op) {
281 JSBinopReduction r(this, node);
282 r.ConvertInputsForShift(left_signed);
283 return r.ChangeToPureOperator(shift_op);
284 }
285
286
287 Reduction JSTypedLowering::ReduceJSComparison(Node* node) {
288 JSBinopReduction r(this, node);
289 if (r.BothInputsAre(Type::String())) {
290 // If both inputs are definitely strings, perform a string comparison.
291 Operator* stringOp;
292 switch (node->opcode()) {
293 case IrOpcode::kJSLessThan:
294 stringOp = simplified()->StringLessThan();
295 break;
296 case IrOpcode::kJSGreaterThan:
297 stringOp = simplified()->StringLessThan();
298 r.SwapInputs(); // a > b => b < a
299 break;
300 case IrOpcode::kJSLessThanOrEqual:
301 stringOp = simplified()->StringLessThanOrEqual();
302 break;
303 case IrOpcode::kJSGreaterThanOrEqual:
304 stringOp = simplified()->StringLessThanOrEqual();
305 r.SwapInputs(); // a >= b => b <= a
306 break;
307 default:
308 return NoChange();
309 }
310 return r.ChangeToPureOperator(stringOp);
311 } else if (r.OneInputCannotBe(Type::String())) {
312 // If one input cannot be a string, then emit a number comparison.
313 Operator* less_than;
314 Operator* less_than_or_equal;
315 if (r.BothInputsAre(Type::Unsigned32())) {
316 less_than = machine()->Uint32LessThan();
317 less_than_or_equal = machine()->Uint32LessThanOrEqual();
318 } else if (r.BothInputsAre(Type::Signed32())) {
319 less_than = machine()->Int32LessThan();
320 less_than_or_equal = machine()->Int32LessThanOrEqual();
321 } else {
322 // TODO(turbofan): mixed signed/unsigned int32 comparisons.
323 r.ConvertInputsToNumber();
324 less_than = simplified()->NumberLessThan();
325 less_than_or_equal = simplified()->NumberLessThanOrEqual();
326 }
327 Operator* comparison;
328 switch (node->opcode()) {
329 case IrOpcode::kJSLessThan:
330 comparison = less_than;
331 break;
332 case IrOpcode::kJSGreaterThan:
333 comparison = less_than;
334 r.SwapInputs(); // a > b => b < a
335 break;
336 case IrOpcode::kJSLessThanOrEqual:
337 comparison = less_than_or_equal;
338 break;
339 case IrOpcode::kJSGreaterThanOrEqual:
340 comparison = less_than_or_equal;
341 r.SwapInputs(); // a >= b => b <= a
342 break;
343 default:
344 return NoChange();
345 }
346 return r.ChangeToPureOperator(comparison);
347 }
348 // TODO(turbofan): relax/remove effects of this operator in other cases.
349 return NoChange(); // Keep a generic comparison.
350 }
351
352
353 Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
354 JSBinopReduction r(this, node);
355
356 if (r.BothInputsAre(Type::Number())) {
357 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
358 }
359 if (r.BothInputsAre(Type::String())) {
360 return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
361 }
362 if (r.BothInputsAre(Type::Receiver())) {
363 return r.ChangeToPureOperator(
364 simplified()->ReferenceEqual(Type::Receiver()), invert);
365 }
366 // TODO(turbofan): js-typed-lowering of Equal(undefined)
367 // TODO(turbofan): js-typed-lowering of Equal(null)
368 // TODO(turbofan): js-typed-lowering of Equal(boolean)
369 return NoChange();
370 }
371
372
373 Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
374 JSBinopReduction r(this, node);
375 if (r.left() == r.right()) {
376 // x === x is always true if x != NaN
377 if (!r.left_type()->Maybe(Type::NaN())) {
378 return ReplaceEagerly(node, invert ? jsgraph()->FalseConstant()
379 : jsgraph()->TrueConstant());
380 }
381 }
382 if (!r.left_type()->Maybe(r.right_type())) {
383 // Type intersection is empty; === is always false unless both
384 // inputs could be strings (one internalized and one not).
385 if (r.OneInputCannotBe(Type::String())) {
386 return ReplaceEagerly(node, invert ? jsgraph()->TrueConstant()
387 : jsgraph()->FalseConstant());
388 }
389 }
390 if (r.OneInputIs(Type::Undefined())) {
391 return r.ChangeToPureOperator(
392 simplified()->ReferenceEqual(Type::Undefined()), invert);
393 }
394 if (r.OneInputIs(Type::Null())) {
395 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Null()),
396 invert);
397 }
398 if (r.OneInputIs(Type::Boolean())) {
399 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
400 invert);
401 }
402 if (r.OneInputIs(Type::Object())) {
403 return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Object()),
404 invert);
405 }
406 if (r.OneInputIs(Type::Receiver())) {
407 return r.ChangeToPureOperator(
408 simplified()->ReferenceEqual(Type::Receiver()), invert);
409 }
410 if (r.BothInputsAre(Type::String())) {
411 return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
412 }
413 if (r.BothInputsAre(Type::Number())) {
414 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
415 }
416 // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types)
417 return NoChange();
418 }
419
420
421 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
422 if (input->opcode() == IrOpcode::kJSToNumber) {
423 // Recursively try to reduce the input first.
424 Reduction result = ReduceJSToNumberInput(input->InputAt(0));
425 if (result.Changed()) {
426 RelaxEffects(input);
427 return result;
428 }
429 return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x)
430 }
431 Type* input_type = NodeProperties::GetBounds(input).upper;
432 if (input_type->Is(Type::Number())) {
433 // JSToNumber(number) => x
434 return Changed(input);
435 }
436 if (input_type->Is(Type::Undefined())) {
437 // JSToNumber(undefined) => #NaN
438 return ReplaceWith(jsgraph()->NaNConstant());
439 }
440 if (input_type->Is(Type::Null())) {
441 // JSToNumber(null) => #0
442 return ReplaceWith(jsgraph()->ZeroConstant());
443 }
444 // TODO(turbofan): js-typed-lowering of ToNumber(boolean)
445 // TODO(turbofan): js-typed-lowering of ToNumber(string)
446 return NoChange();
447 }
448
449
450 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
451 if (input->opcode() == IrOpcode::kJSToString) {
452 // Recursively try to reduce the input first.
453 Reduction result = ReduceJSToStringInput(input->InputAt(0));
454 if (result.Changed()) {
455 RelaxEffects(input);
456 return result;
457 }
458 return Changed(input); // JSToString(JSToString(x)) => JSToString(x)
459 }
460 Type* input_type = NodeProperties::GetBounds(input).upper;
461 if (input_type->Is(Type::String())) {
462 return Changed(input); // JSToString(string) => x
463 }
464 if (input_type->Is(Type::Undefined())) {
465 return ReplaceWith(jsgraph()->HeapConstant(
466 graph()->zone()->isolate()->factory()->undefined_string()));
467 }
468 if (input_type->Is(Type::Null())) {
469 return ReplaceWith(jsgraph()->HeapConstant(
470 graph()->zone()->isolate()->factory()->null_string()));
471 }
472 // TODO(turbofan): js-typed-lowering of ToString(boolean)
473 // TODO(turbofan): js-typed-lowering of ToString(number)
474 return NoChange();
475 }
476
477
478 Reduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) {
479 if (input->opcode() == IrOpcode::kJSToBoolean) {
480 // Recursively try to reduce the input first.
481 Reduction result = ReduceJSToBooleanInput(input->InputAt(0));
482 if (result.Changed()) {
483 RelaxEffects(input);
484 return result;
485 }
486 return Changed(input); // JSToBoolean(JSToBoolean(x)) => JSToBoolean(x)
487 }
488 Type* input_type = NodeProperties::GetBounds(input).upper;
489 if (input_type->Is(Type::Boolean())) {
490 return Changed(input); // JSToBoolean(boolean) => x
491 }
492 if (input_type->Is(Type::Undefined())) {
493 // JSToBoolean(undefined) => #false
494 return ReplaceWith(jsgraph()->FalseConstant());
495 }
496 if (input_type->Is(Type::Null())) {
497 // JSToBoolean(null) => #false
498 return ReplaceWith(jsgraph()->FalseConstant());
499 }
500 if (input_type->Is(Type::DetectableReceiver())) {
501 // JSToBoolean(detectable) => #true
502 return ReplaceWith(jsgraph()->TrueConstant());
503 }
504 if (input_type->Is(Type::Undetectable())) {
505 // JSToBoolean(undetectable) => #false
506 return ReplaceWith(jsgraph()->FalseConstant());
507 }
508 if (input_type->Is(Type::Number())) {
509 // JSToBoolean(number) => BooleanNot(NumberEqual(x, #0))
510 Node* cmp = graph()->NewNode(simplified()->NumberEqual(), input,
511 jsgraph()->ZeroConstant());
512 Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp);
513 ReplaceEagerly(input, inv);
514 // TODO(titzer): Ugly. ReplaceEagerly smashes all uses. Smash it back here.
515 cmp->ReplaceInput(0, input);
516 return Changed(inv);
517 }
518 // TODO(turbofan): js-typed-lowering of ToBoolean(string)
519 return NoChange();
520 }
521
522
523 static Reduction ReplaceWithReduction(Node* node, Reduction reduction) {
524 if (reduction.Changed()) {
525 ReplaceUses(node, reduction.replacement(), NULL);
526 return reduction;
527 }
528 return Reducer::NoChange();
529 }
530
531
532 Reduction JSTypedLowering::Reduce(Node* node) {
533 switch (node->opcode()) {
534 case IrOpcode::kJSEqual:
535 return ReduceJSEqual(node, false);
536 case IrOpcode::kJSNotEqual:
537 return ReduceJSEqual(node, true);
538 case IrOpcode::kJSStrictEqual:
539 return ReduceJSStrictEqual(node, false);
540 case IrOpcode::kJSStrictNotEqual:
541 return ReduceJSStrictEqual(node, true);
542 case IrOpcode::kJSLessThan: // fall through
543 case IrOpcode::kJSGreaterThan: // fall through
544 case IrOpcode::kJSLessThanOrEqual: // fall through
545 case IrOpcode::kJSGreaterThanOrEqual:
546 return ReduceJSComparison(node);
547 case IrOpcode::kJSBitwiseOr:
548 return ReduceI32Binop(node, true, true, machine()->Word32Or());
549 case IrOpcode::kJSBitwiseXor:
550 return ReduceI32Binop(node, true, true, machine()->Word32Xor());
551 case IrOpcode::kJSBitwiseAnd:
552 return ReduceI32Binop(node, true, true, machine()->Word32And());
553 case IrOpcode::kJSShiftLeft:
554 return ReduceI32Shift(node, true, machine()->Word32Shl());
555 case IrOpcode::kJSShiftRight:
556 return ReduceI32Shift(node, true, machine()->Word32Sar());
557 case IrOpcode::kJSShiftRightLogical:
558 return ReduceI32Shift(node, false, machine()->Word32Shr());
559 case IrOpcode::kJSAdd:
560 return ReduceJSAdd(node);
561 case IrOpcode::kJSSubtract:
562 return ReduceNumberBinop(node, simplified()->NumberSubtract());
563 case IrOpcode::kJSMultiply:
564 return ReduceNumberBinop(node, simplified()->NumberMultiply());
565 case IrOpcode::kJSDivide:
566 return ReduceNumberBinop(node, simplified()->NumberDivide());
567 case IrOpcode::kJSModulus:
568 return ReduceNumberBinop(node, simplified()->NumberModulus());
569 case IrOpcode::kJSUnaryNot: {
570 Reduction result = ReduceJSToBooleanInput(node->InputAt(0));
571 Node* value;
572 if (result.Changed()) {
573 // !x => BooleanNot(x)
574 value =
575 graph()->NewNode(simplified()->BooleanNot(), result.replacement());
576 ReplaceUses(node, value, NULL);
577 return Changed(value);
578 } else {
579 // !x => BooleanNot(JSToBoolean(x))
580 value = graph()->NewNode(simplified()->BooleanNot(), node);
581 node->set_op(javascript()->ToBoolean());
582 ReplaceUses(node, value, node);
583 // Note: ReplaceUses() smashes all uses, so smash it back here.
584 value->ReplaceInput(0, node);
585 return ReplaceWith(value);
586 }
587 }
588 case IrOpcode::kJSToBoolean:
589 return ReplaceWithReduction(node,
590 ReduceJSToBooleanInput(node->InputAt(0)));
591 case IrOpcode::kJSToNumber:
592 return ReplaceWithReduction(node,
593 ReduceJSToNumberInput(node->InputAt(0)));
594 case IrOpcode::kJSToString:
595 return ReplaceWithReduction(node,
596 ReduceJSToStringInput(node->InputAt(0)));
597 default:
598 break;
599 }
600 return NoChange();
601 }
602 }
603 }
604 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/js-typed-lowering.h ('k') | src/compiler/linkage.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698