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

Side by Side Diff: src/compiler/ia32/instruction-selector-ia32.cc

Issue 447203002: Add Uint32AddWithOverflow and Uint32SubWithOverflow machine operators. Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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/arm64/instruction-selector-arm64.cc ('k') | src/compiler/instruction-selector.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/instruction-selector-impl.h" 5 #include "src/compiler/instruction-selector-impl.h"
6 #include "src/compiler/node-matchers.h" 6 #include "src/compiler/node-matchers.h"
7 #include "src/compiler/node-properties-inl.h" 7 #include "src/compiler/node-properties-inl.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, 152 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL,
153 g.UseRegister(base), g.UseImmediate(index), val); 153 g.UseRegister(base), g.UseImmediate(index), val);
154 } else { // store [%base + %index], %|#value 154 } else { // store [%base + %index], %|#value
155 Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL, 155 Emit(opcode | AddressingModeField::encode(kMode_MR1I), NULL,
156 g.UseRegister(base), g.UseRegister(index), val); 156 g.UseRegister(base), g.UseRegister(index), val);
157 } 157 }
158 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] 158 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K]
159 } 159 }
160 160
161 161
162 // Shared routine for multiple binary operations.
163 static void VisitBinop(InstructionSelector* selector, Node* node, 162 static void VisitBinop(InstructionSelector* selector, Node* node,
164 InstructionCode opcode, FlagsContinuation* cont) { 163 InstructionCode opcode, FlagsContinuation* cont) {
165 IA32OperandGenerator g(selector); 164 IA32OperandGenerator g(selector);
166 Int32BinopMatcher m(node); 165 Int32BinopMatcher m(node);
167 InstructionOperand* inputs[4]; 166 InstructionOperand* inputs[4];
168 size_t input_count = 0; 167 size_t input_count = 0;
169 InstructionOperand* outputs[2]; 168 InstructionOperand* outputs[2];
170 size_t output_count = 0; 169 size_t output_count = 0;
171 170
172 // TODO(turbofan): match complex addressing modes. 171 // TODO(turbofan): match complex addressing modes.
(...skipping 22 matching lines...) Expand all
195 DCHECK_NE(0, output_count); 194 DCHECK_NE(0, output_count);
196 DCHECK_GE(ARRAY_SIZE(inputs), input_count); 195 DCHECK_GE(ARRAY_SIZE(inputs), input_count);
197 DCHECK_GE(ARRAY_SIZE(outputs), output_count); 196 DCHECK_GE(ARRAY_SIZE(outputs), output_count);
198 197
199 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, 198 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
200 outputs, input_count, inputs); 199 outputs, input_count, inputs);
201 if (cont->IsBranch()) instr->MarkAsControl(); 200 if (cont->IsBranch()) instr->MarkAsControl();
202 } 201 }
203 202
204 203
205 // Shared routine for multiple binary operations.
206 static void VisitBinop(InstructionSelector* selector, Node* node, 204 static void VisitBinop(InstructionSelector* selector, Node* node,
207 InstructionCode opcode) { 205 InstructionCode opcode) {
208 FlagsContinuation cont; 206 FlagsContinuation cont;
209 VisitBinop(selector, node, opcode, &cont); 207 VisitBinop(selector, node, opcode, &cont);
210 } 208 }
211 209
212 210
211 static void VisitBinop(InstructionSelector* selector, Node* node,
212 InstructionCode opcode,
213 FlagsCondition overflow_condition) {
214 if (Node* overflow = node->FindProjection(1)) {
215 FlagsContinuation cont(overflow_condition, overflow);
216 return VisitBinop(selector, node, opcode, &cont);
217 }
218 FlagsContinuation cont;
219 return VisitBinop(selector, node, opcode, &cont);
220 }
221
222
213 void InstructionSelector::VisitWord32And(Node* node) { 223 void InstructionSelector::VisitWord32And(Node* node) {
214 VisitBinop(this, node, kIA32And); 224 VisitBinop(this, node, kIA32And);
215 } 225 }
216 226
217 227
218 void InstructionSelector::VisitWord32Or(Node* node) { 228 void InstructionSelector::VisitWord32Or(Node* node) {
219 VisitBinop(this, node, kIA32Or); 229 VisitBinop(this, node, kIA32Or);
220 } 230 }
221 231
222 232
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 void InstructionSelector::VisitWord32Sar(Node* node) { 279 void InstructionSelector::VisitWord32Sar(Node* node) {
270 VisitShift(this, node, kIA32Sar); 280 VisitShift(this, node, kIA32Sar);
271 } 281 }
272 282
273 283
274 void InstructionSelector::VisitInt32Add(Node* node) { 284 void InstructionSelector::VisitInt32Add(Node* node) {
275 VisitBinop(this, node, kIA32Add); 285 VisitBinop(this, node, kIA32Add);
276 } 286 }
277 287
278 288
289 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
290 VisitBinop(this, node, kIA32Add, kOverflow);
291 }
292
293
294 void InstructionSelector::VisitUint32AddWithOverflow(Node* node) {
295 VisitBinop(this, node, kIA32Add, kUnsignedLessThan);
296 }
297
298
279 void InstructionSelector::VisitInt32Sub(Node* node) { 299 void InstructionSelector::VisitInt32Sub(Node* node) {
280 IA32OperandGenerator g(this); 300 IA32OperandGenerator g(this);
281 Int32BinopMatcher m(node); 301 Int32BinopMatcher m(node);
282 if (m.left().Is(0)) { 302 if (m.left().Is(0)) {
283 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); 303 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node()));
284 } else { 304 } else {
285 VisitBinop(this, node, kIA32Sub); 305 VisitBinop(this, node, kIA32Sub);
286 } 306 }
287 } 307 }
288 308
289 309
310 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
311 VisitBinop(this, node, kIA32Sub, kOverflow);
312 }
313
314
315 void InstructionSelector::VisitUint32SubWithOverflow(Node* node) {
316 VisitBinop(this, node, kIA32Sub, kUnsignedLessThan);
317 }
318
319
290 void InstructionSelector::VisitInt32Mul(Node* node) { 320 void InstructionSelector::VisitInt32Mul(Node* node) {
291 IA32OperandGenerator g(this); 321 IA32OperandGenerator g(this);
292 Node* left = node->InputAt(0); 322 Node* left = node->InputAt(0);
293 Node* right = node->InputAt(1); 323 Node* right = node->InputAt(1);
294 if (g.CanBeImmediate(right)) { 324 if (g.CanBeImmediate(right)) {
295 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), 325 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left),
296 g.UseImmediate(right)); 326 g.UseImmediate(right));
297 } else if (g.CanBeImmediate(left)) { 327 } else if (g.CanBeImmediate(left)) {
298 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(right), 328 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(right),
299 g.UseImmediate(left)); 329 g.UseImmediate(left));
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 440
411 void InstructionSelector::VisitFloat64Mod(Node* node) { 441 void InstructionSelector::VisitFloat64Mod(Node* node) {
412 IA32OperandGenerator g(this); 442 IA32OperandGenerator g(this);
413 InstructionOperand* temps[] = {g.TempRegister(eax)}; 443 InstructionOperand* temps[] = {g.TempRegister(eax)};
414 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), 444 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node),
415 g.UseDoubleRegister(node->InputAt(0)), 445 g.UseDoubleRegister(node->InputAt(0)),
416 g.UseDoubleRegister(node->InputAt(1)), 1, temps); 446 g.UseDoubleRegister(node->InputAt(1)), 1, temps);
417 } 447 }
418 448
419 449
420 void InstructionSelector::VisitInt32AddWithOverflow(Node* node,
421 FlagsContinuation* cont) {
422 VisitBinop(this, node, kIA32Add, cont);
423 }
424
425
426 void InstructionSelector::VisitInt32SubWithOverflow(Node* node,
427 FlagsContinuation* cont) {
428 VisitBinop(this, node, kIA32Sub, cont);
429 }
430
431
432 // Shared routine for multiple compare operations. 450 // Shared routine for multiple compare operations.
433 static inline void VisitCompare(InstructionSelector* selector, 451 static inline void VisitCompare(InstructionSelector* selector,
434 InstructionCode opcode, 452 InstructionCode opcode,
435 InstructionOperand* left, 453 InstructionOperand* left,
436 InstructionOperand* right, 454 InstructionOperand* right,
437 FlagsContinuation* cont) { 455 FlagsContinuation* cont) {
438 IA32OperandGenerator g(selector); 456 IA32OperandGenerator g(selector);
439 if (cont->IsBranch()) { 457 if (cont->IsBranch()) {
440 selector->Emit(cont->Encode(opcode), NULL, left, right, 458 selector->Emit(cont->Encode(opcode), NULL, left, right,
441 g.Label(cont->true_block()), 459 g.Label(cont->true_block()),
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 void InstructionSelector::VisitFloat64Compare(Node* node, 511 void InstructionSelector::VisitFloat64Compare(Node* node,
494 FlagsContinuation* cont) { 512 FlagsContinuation* cont) {
495 IA32OperandGenerator g(this); 513 IA32OperandGenerator g(this);
496 Node* left = node->InputAt(0); 514 Node* left = node->InputAt(0);
497 Node* right = node->InputAt(1); 515 Node* right = node->InputAt(1);
498 VisitCompare(this, kSSEFloat64Cmp, g.UseDoubleRegister(left), g.Use(right), 516 VisitCompare(this, kSSEFloat64Cmp, g.UseDoubleRegister(left), g.Use(right),
499 cont); 517 cont);
500 } 518 }
501 519
502 520
521 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
522 BasicBlock* fbranch) {
523 OperandGenerator g(this);
524 Node* user = branch;
525 Node* value = branch->InputAt(0);
526
527 FlagsContinuation cont(kNotEqual, tbranch, fbranch);
528
529 // If we can fall through to the true block, invert the branch.
530 if (IsNextInAssemblyOrder(tbranch)) {
531 cont.Negate();
532 cont.SwapBlocks();
533 }
534
535 // Try to combine with comparisons against 0 by simply inverting the branch.
536 while (CanCover(user, value)) {
537 if (value->opcode() == IrOpcode::kWord32Equal) {
538 Int32BinopMatcher m(value);
539 if (m.right().Is(0)) {
540 user = value;
541 value = m.left().node();
542 cont.Negate();
543 } else {
544 break;
545 }
546 } else {
547 break;
548 }
549 }
550
551 // Try to combine the branch with a comparison.
552 if (CanCover(user, value)) {
553 switch (value->opcode()) {
554 case IrOpcode::kWord32Equal:
555 cont.OverwriteAndNegateIfEqual(kEqual);
556 return VisitWord32Compare(value, &cont);
557 case IrOpcode::kInt32LessThan:
558 cont.OverwriteAndNegateIfEqual(kSignedLessThan);
559 return VisitWord32Compare(value, &cont);
560 case IrOpcode::kInt32LessThanOrEqual:
561 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
562 return VisitWord32Compare(value, &cont);
563 case IrOpcode::kUint32LessThan:
564 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
565 return VisitWord32Compare(value, &cont);
566 case IrOpcode::kUint32LessThanOrEqual:
567 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
568 return VisitWord32Compare(value, &cont);
569 case IrOpcode::kFloat64Equal:
570 cont.OverwriteAndNegateIfEqual(kUnorderedEqual);
571 return VisitFloat64Compare(value, &cont);
572 case IrOpcode::kFloat64LessThan:
573 cont.OverwriteAndNegateIfEqual(kUnorderedLessThan);
574 return VisitFloat64Compare(value, &cont);
575 case IrOpcode::kFloat64LessThanOrEqual:
576 cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
577 return VisitFloat64Compare(value, &cont);
578 case IrOpcode::kProjection:
579 // Check if this is the overflow output projection of an
580 // <Operation>WithOverflow node.
581 if (OpParameter<int32_t>(value) == 1) {
582 // We cannot combine the <Operation>WithOverflow with this branch
583 // unless the 0th projection (the use of the actual value of the
584 // <Operation> is either NULL, which means there's no use of the
585 // actual value, or was already defined, which means it is scheduled
586 // *AFTER* this branch).
587 Node* node = value->InputAt(0);
588 Node* result = node->FindProjection(0);
589 if (result == NULL || IsDefined(result)) {
590 switch (node->opcode()) {
591 case IrOpcode::kInt32AddWithOverflow:
592 cont.OverwriteAndNegateIfEqual(kOverflow);
593 return VisitBinop(this, node, kIA32Add, &cont);
594 case IrOpcode::kUint32AddWithOverflow:
595 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
596 return VisitBinop(this, node, kIA32Add, &cont);
597 case IrOpcode::kInt32SubWithOverflow:
598 cont.OverwriteAndNegateIfEqual(kOverflow);
599 return VisitBinop(this, node, kIA32Sub, &cont);
600 case IrOpcode::kUint32SubWithOverflow:
601 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
602 return VisitBinop(this, node, kIA32Sub, &cont);
603 default:
604 break;
605 }
606 }
607 }
608 break;
609 default:
610 break;
611 }
612 }
613
614 // Branch could not be combined with a compare, emit compare against 0.
615 VisitWord32Test(value, &cont);
616 }
617
618
503 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, 619 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation,
504 BasicBlock* deoptimization) { 620 BasicBlock* deoptimization) {
505 IA32OperandGenerator g(this); 621 IA32OperandGenerator g(this);
506 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call); 622 CallDescriptor* descriptor = OpParameter<CallDescriptor*>(call);
507 CallBuffer buffer(zone(), descriptor); 623 CallBuffer buffer(zone(), descriptor);
508 624
509 // Compute InstructionOperands for inputs and outputs. 625 // Compute InstructionOperands for inputs and outputs.
510 InitializeCallBuffer(call, &buffer, true, true, continuation, deoptimization); 626 InitializeCallBuffer(call, &buffer, true, true, continuation, deoptimization);
511 627
512 // Push any stack arguments. 628 // Push any stack arguments.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 if (descriptor->kind() == CallDescriptor::kCallAddress && 667 if (descriptor->kind() == CallDescriptor::kCallAddress &&
552 buffer.pushed_count > 0) { 668 buffer.pushed_count > 0) {
553 DCHECK(deoptimization == NULL && continuation == NULL); 669 DCHECK(deoptimization == NULL && continuation == NULL);
554 Emit(kPopStack | MiscField::encode(buffer.pushed_count), NULL); 670 Emit(kPopStack | MiscField::encode(buffer.pushed_count), NULL);
555 } 671 }
556 } 672 }
557 673
558 } // namespace compiler 674 } // namespace compiler
559 } // namespace internal 675 } // namespace internal
560 } // namespace v8 676 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/arm64/instruction-selector-arm64.cc ('k') | src/compiler/instruction-selector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698