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

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

Issue 415403005: [turbofan] Support for combining branches with <Operation>WithOverflow. (Closed) 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 | « no previous file | src/compiler/arm64/instruction-selector-arm64.cc » ('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-intrinsics.h" 7 #include "src/compiler-intrinsics.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 return true; 242 return true;
243 } 243 }
244 if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) { 244 if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) {
245 *input_count_return = 2; 245 *input_count_return = 2;
246 return true; 246 return true;
247 } 247 }
248 return false; 248 return false;
249 } 249 }
250 250
251 251
252 // Shared routine for multiple binary operations.
253 static void VisitBinop(InstructionSelector* selector, Node* node, 252 static void VisitBinop(InstructionSelector* selector, Node* node,
254 InstructionCode opcode, InstructionCode reverse_opcode) { 253 InstructionCode opcode, InstructionCode reverse_opcode,
254 FlagsContinuation* cont) {
255 ArmOperandGenerator g(selector); 255 ArmOperandGenerator g(selector);
256 Int32BinopMatcher m(node); 256 Int32BinopMatcher m(node);
257 InstructionOperand* inputs[3]; 257 InstructionOperand* inputs[5];
258 size_t input_count = 0;
259 InstructionOperand* outputs[1] = {g.DefineAsRegister(node)};
260 const size_t output_count = ARRAY_SIZE(outputs);
261
262 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
263 &input_count, &inputs[1])) {
264 inputs[0] = g.UseRegister(m.left().node());
265 input_count++;
266 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode,
267 m.left().node(), &input_count,
268 &inputs[1])) {
269 inputs[0] = g.UseRegister(m.right().node());
270 opcode = reverse_opcode;
271 input_count++;
272 } else {
273 opcode |= AddressingModeField::encode(kMode_Operand2_R);
274 inputs[input_count++] = g.UseRegister(m.left().node());
275 inputs[input_count++] = g.UseRegister(m.right().node());
276 }
277
278 ASSERT_NE(0, input_count);
279 ASSERT_GE(ARRAY_SIZE(inputs), input_count);
280 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode));
281
282 selector->Emit(opcode, output_count, outputs, input_count, inputs);
283 }
284
285
286 static void VisitBinopWithOverflow(InstructionSelector* selector, Node* node,
287 InstructionCode opcode,
288 InstructionCode reverse_opcode) {
289 ArmOperandGenerator g(selector);
290 Int32BinopMatcher m(node);
291 InstructionOperand* inputs[3];
292 size_t input_count = 0; 258 size_t input_count = 0;
293 InstructionOperand* outputs[2]; 259 InstructionOperand* outputs[2];
294 size_t output_count = 0; 260 size_t output_count = 0;
295 261
296 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), 262 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
297 &input_count, &inputs[1])) { 263 &input_count, &inputs[1])) {
298 inputs[0] = g.UseRegister(m.left().node()); 264 inputs[0] = g.UseRegister(m.left().node());
299 input_count++; 265 input_count++;
300 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode, 266 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode,
301 m.left().node(), &input_count, 267 m.left().node(), &input_count,
302 &inputs[1])) { 268 &inputs[1])) {
303 inputs[0] = g.UseRegister(m.right().node()); 269 inputs[0] = g.UseRegister(m.right().node());
304 opcode = reverse_opcode; 270 opcode = reverse_opcode;
305 input_count++; 271 input_count++;
306 } else { 272 } else {
307 opcode |= AddressingModeField::encode(kMode_Operand2_R); 273 opcode |= AddressingModeField::encode(kMode_Operand2_R);
308 inputs[input_count++] = g.UseRegister(m.left().node()); 274 inputs[input_count++] = g.UseRegister(m.left().node());
309 inputs[input_count++] = g.UseRegister(m.right().node()); 275 inputs[input_count++] = g.UseRegister(m.right().node());
310 } 276 }
311 277
312 // Define outputs depending on the projections. 278 if (cont->IsBranch()) {
313 Node* projections[2]; 279 inputs[input_count++] = g.Label(cont->true_block());
314 node->CollectProjections(ARRAY_SIZE(projections), projections); 280 inputs[input_count++] = g.Label(cont->false_block());
315 if (projections[0]) {
316 outputs[output_count++] = g.DefineAsRegister(projections[0]);
317 } 281 }
318 if (projections[1]) { 282
319 opcode |= FlagsModeField::encode(kFlags_set); 283 outputs[output_count++] = g.DefineAsRegister(node);
320 opcode |= FlagsConditionField::encode(kOverflow); 284 if (cont->IsSet()) {
321 outputs[output_count++] = g.DefineAsRegister(projections[1]); 285 outputs[output_count++] = g.DefineAsRegister(cont->result());
322 } 286 }
323 287
324 ASSERT_NE(0, input_count); 288 ASSERT_NE(0, input_count);
325 ASSERT_NE(0, output_count); 289 ASSERT_NE(0, output_count);
326 ASSERT_GE(ARRAY_SIZE(inputs), input_count); 290 ASSERT_GE(ARRAY_SIZE(inputs), input_count);
327 ASSERT_GE(ARRAY_SIZE(outputs), output_count); 291 ASSERT_GE(ARRAY_SIZE(outputs), output_count);
328 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode)); 292 ASSERT_NE(kMode_None, AddressingModeField::decode(opcode));
329 293
330 selector->Emit(opcode, output_count, outputs, input_count, inputs); 294 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
295 outputs, input_count, inputs);
296 if (cont->IsBranch()) instr->MarkAsControl();
331 } 297 }
332 298
333 299
300 static void VisitBinop(InstructionSelector* selector, Node* node,
301 InstructionCode opcode, InstructionCode reverse_opcode) {
302 FlagsContinuation cont;
303 VisitBinop(selector, node, opcode, reverse_opcode, &cont);
304 }
305
306
334 void InstructionSelector::VisitLoad(Node* node) { 307 void InstructionSelector::VisitLoad(Node* node) {
335 MachineRepresentation rep = OpParameter<MachineRepresentation>(node); 308 MachineRepresentation rep = OpParameter<MachineRepresentation>(node);
336 ArmOperandGenerator g(this); 309 ArmOperandGenerator g(this);
337 Node* base = node->InputAt(0); 310 Node* base = node->InputAt(0);
338 Node* index = node->InputAt(1); 311 Node* index = node->InputAt(1);
339 312
340 InstructionOperand* result = rep == kMachineFloat64 313 InstructionOperand* result = rep == kMachineFloat64
341 ? g.DefineAsDoubleRegister(node) 314 ? g.DefineAsDoubleRegister(node)
342 : g.DefineAsRegister(node); 315 : g.DefineAsRegister(node);
343 316
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { 563 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) {
591 Int32BinopMatcher mright(m.right().node()); 564 Int32BinopMatcher mright(m.right().node());
592 Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mright.left().node()), 565 Emit(kArmMla, g.DefineAsRegister(node), g.UseRegister(mright.left().node()),
593 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); 566 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node()));
594 return; 567 return;
595 } 568 }
596 VisitBinop(this, node, kArmAdd, kArmAdd); 569 VisitBinop(this, node, kArmAdd, kArmAdd);
597 } 570 }
598 571
599 572
600 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
601 VisitBinopWithOverflow(this, node, kArmAdd, kArmAdd);
602 }
603
604
605 void InstructionSelector::VisitInt32Sub(Node* node) { 573 void InstructionSelector::VisitInt32Sub(Node* node) {
606 ArmOperandGenerator g(this); 574 ArmOperandGenerator g(this);
607 Int32BinopMatcher m(node); 575 Int32BinopMatcher m(node);
608 if (CpuFeatures::IsSupported(MLS) && m.right().IsInt32Mul() && 576 if (CpuFeatures::IsSupported(MLS) && m.right().IsInt32Mul() &&
609 CanCover(node, m.right().node())) { 577 CanCover(node, m.right().node())) {
610 Int32BinopMatcher mright(m.right().node()); 578 Int32BinopMatcher mright(m.right().node());
611 Emit(kArmMls, g.DefineAsRegister(node), g.UseRegister(mright.left().node()), 579 Emit(kArmMls, g.DefineAsRegister(node), g.UseRegister(mright.left().node()),
612 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); 580 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node()));
613 return; 581 return;
614 } 582 }
615 VisitBinop(this, node, kArmSub, kArmRsb); 583 VisitBinop(this, node, kArmSub, kArmRsb);
616 } 584 }
617 585
618 586
619 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
620 VisitBinopWithOverflow(this, node, kArmSub, kArmRsb);
621 }
622
623
624 void InstructionSelector::VisitInt32Mul(Node* node) { 587 void InstructionSelector::VisitInt32Mul(Node* node) {
625 ArmOperandGenerator g(this); 588 ArmOperandGenerator g(this);
626 Int32BinopMatcher m(node); 589 Int32BinopMatcher m(node);
627 if (m.right().HasValue() && m.right().Value() > 0) { 590 if (m.right().HasValue() && m.right().Value() > 0) {
628 int32_t value = m.right().Value(); 591 int32_t value = m.right().Value();
629 if (IsPowerOf2(value - 1)) { 592 if (IsPowerOf2(value - 1)) {
630 Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_R_LSL_I), 593 Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_R_LSL_I),
631 g.DefineAsRegister(node), g.UseRegister(m.left().node()), 594 g.DefineAsRegister(node), g.UseRegister(m.left().node()),
632 g.UseRegister(m.left().node()), 595 g.UseRegister(m.left().node()),
633 g.TempImmediate(WhichPowerOf2(value - 1))); 596 g.TempImmediate(WhichPowerOf2(value - 1)));
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 823
861 // Caller clean up of stack for C-style calls. 824 // Caller clean up of stack for C-style calls.
862 if (descriptor->kind() == CallDescriptor::kCallAddress && 825 if (descriptor->kind() == CallDescriptor::kCallAddress &&
863 buffer.pushed_count > 0) { 826 buffer.pushed_count > 0) {
864 ASSERT(deoptimization == NULL && continuation == NULL); 827 ASSERT(deoptimization == NULL && continuation == NULL);
865 Emit(kArmDrop | MiscField::encode(buffer.pushed_count), NULL); 828 Emit(kArmDrop | MiscField::encode(buffer.pushed_count), NULL);
866 } 829 }
867 } 830 }
868 831
869 832
833 void InstructionSelector::VisitInt32AddWithOverflow(Node* node,
834 FlagsContinuation* cont) {
835 VisitBinop(this, node, kArmAdd, kArmAdd, cont);
836 }
837
838
839 void InstructionSelector::VisitInt32SubWithOverflow(Node* node,
840 FlagsContinuation* cont) {
841 VisitBinop(this, node, kArmSub, kArmRsb, cont);
842 }
843
844
870 // Shared routine for multiple compare operations. 845 // Shared routine for multiple compare operations.
871 static void VisitWordCompare(InstructionSelector* selector, Node* node, 846 static void VisitWordCompare(InstructionSelector* selector, Node* node,
872 InstructionCode opcode, FlagsContinuation* cont, 847 InstructionCode opcode, FlagsContinuation* cont,
873 bool commutative, bool requires_output) { 848 bool commutative) {
874 ArmOperandGenerator g(selector); 849 ArmOperandGenerator g(selector);
875 Int32BinopMatcher m(node); 850 Int32BinopMatcher m(node);
876 InstructionOperand* inputs[5]; 851 InstructionOperand* inputs[5];
877 size_t input_count = 0; 852 size_t input_count = 0;
878 InstructionOperand* outputs[1]; 853 InstructionOperand* outputs[1];
879 size_t output_count = 0; 854 size_t output_count = 0;
880 855
881 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), 856 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
882 &input_count, &inputs[1])) { 857 &input_count, &inputs[1])) {
883 inputs[0] = g.UseRegister(m.left().node()); 858 inputs[0] = g.UseRegister(m.left().node());
884 input_count++; 859 input_count++;
885 } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(), 860 } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(),
886 &input_count, &inputs[1])) { 861 &input_count, &inputs[1])) {
887 if (!commutative) cont->Commute(); 862 if (!commutative) cont->Commute();
888 inputs[0] = g.UseRegister(m.right().node()); 863 inputs[0] = g.UseRegister(m.right().node());
889 input_count++; 864 input_count++;
890 } else { 865 } else {
891 opcode |= AddressingModeField::encode(kMode_Operand2_R); 866 opcode |= AddressingModeField::encode(kMode_Operand2_R);
892 inputs[input_count++] = g.UseRegister(m.left().node()); 867 inputs[input_count++] = g.UseRegister(m.left().node());
893 inputs[input_count++] = g.UseRegister(m.right().node()); 868 inputs[input_count++] = g.UseRegister(m.right().node());
894 } 869 }
895 870
896 if (cont->IsBranch()) { 871 if (cont->IsBranch()) {
897 if (requires_output) {
898 outputs[output_count++] = g.DefineAsRegister(node);
899 }
900 inputs[input_count++] = g.Label(cont->true_block()); 872 inputs[input_count++] = g.Label(cont->true_block());
901 inputs[input_count++] = g.Label(cont->false_block()); 873 inputs[input_count++] = g.Label(cont->false_block());
902 } else { 874 } else {
903 ASSERT(cont->IsSet()); 875 ASSERT(cont->IsSet());
904 outputs[output_count++] = g.DefineAsRegister(cont->result()); 876 outputs[output_count++] = g.DefineAsRegister(cont->result());
905 } 877 }
906 878
907 ASSERT_NE(0, input_count); 879 ASSERT_NE(0, input_count);
908 ASSERT_GE(ARRAY_SIZE(inputs), input_count); 880 ASSERT_GE(ARRAY_SIZE(inputs), input_count);
909 ASSERT_GE(ARRAY_SIZE(outputs), output_count); 881 ASSERT_GE(ARRAY_SIZE(outputs), output_count);
910 882
911 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, 883 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
912 outputs, input_count, inputs); 884 outputs, input_count, inputs);
913 if (cont->IsBranch()) instr->MarkAsControl(); 885 if (cont->IsBranch()) instr->MarkAsControl();
914 } 886 }
915 887
916 888
917 void InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) { 889 void InstructionSelector::VisitWord32Test(Node* node, FlagsContinuation* cont) {
918 switch (node->opcode()) { 890 switch (node->opcode()) {
919 case IrOpcode::kInt32Add: 891 case IrOpcode::kInt32Add:
920 return VisitWordCompare(this, node, kArmCmn, cont, true, false); 892 return VisitWordCompare(this, node, kArmCmn, cont, true);
921 case IrOpcode::kInt32Sub: 893 case IrOpcode::kInt32Sub:
922 return VisitWordCompare(this, node, kArmCmp, cont, false, false); 894 return VisitWordCompare(this, node, kArmCmp, cont, false);
923 case IrOpcode::kWord32And: 895 case IrOpcode::kWord32And:
924 return VisitWordCompare(this, node, kArmTst, cont, true, false); 896 return VisitWordCompare(this, node, kArmTst, cont, true);
925 case IrOpcode::kWord32Or: 897 case IrOpcode::kWord32Or:
926 return VisitWordCompare(this, node, kArmOrr, cont, true, true); 898 return VisitBinop(this, node, kArmOrr, kArmOrr, cont);
927 case IrOpcode::kWord32Xor: 899 case IrOpcode::kWord32Xor:
928 return VisitWordCompare(this, node, kArmTeq, cont, true, false); 900 return VisitWordCompare(this, node, kArmTeq, cont, true);
929 default: 901 default:
930 break; 902 break;
931 } 903 }
932 904
933 ArmOperandGenerator g(this); 905 ArmOperandGenerator g(this);
934 InstructionCode opcode = 906 InstructionCode opcode =
935 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R); 907 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R);
936 if (cont->IsBranch()) { 908 if (cont->IsBranch()) {
937 Emit(opcode, NULL, g.UseRegister(node), g.UseRegister(node), 909 Emit(opcode, NULL, g.UseRegister(node), g.UseRegister(node),
938 g.Label(cont->true_block()), 910 g.Label(cont->true_block()),
939 g.Label(cont->false_block()))->MarkAsControl(); 911 g.Label(cont->false_block()))->MarkAsControl();
940 } else { 912 } else {
941 Emit(opcode, g.DefineAsRegister(cont->result()), g.UseRegister(node), 913 Emit(opcode, g.DefineAsRegister(cont->result()), g.UseRegister(node),
942 g.UseRegister(node)); 914 g.UseRegister(node));
943 } 915 }
944 } 916 }
945 917
946 918
947 void InstructionSelector::VisitWord32Compare(Node* node, 919 void InstructionSelector::VisitWord32Compare(Node* node,
948 FlagsContinuation* cont) { 920 FlagsContinuation* cont) {
949 VisitWordCompare(this, node, kArmCmp, cont, false, false); 921 VisitWordCompare(this, node, kArmCmp, cont, false);
950 } 922 }
951 923
952 924
953 void InstructionSelector::VisitFloat64Compare(Node* node, 925 void InstructionSelector::VisitFloat64Compare(Node* node,
954 FlagsContinuation* cont) { 926 FlagsContinuation* cont) {
955 ArmOperandGenerator g(this); 927 ArmOperandGenerator g(this);
956 Float64BinopMatcher m(node); 928 Float64BinopMatcher m(node);
957 if (cont->IsBranch()) { 929 if (cont->IsBranch()) {
958 Emit(cont->Encode(kArmVcmpF64), NULL, g.UseDoubleRegister(m.left().node()), 930 Emit(cont->Encode(kArmVcmpF64), NULL, g.UseDoubleRegister(m.left().node()),
959 g.UseDoubleRegister(m.right().node()), g.Label(cont->true_block()), 931 g.UseDoubleRegister(m.right().node()), g.Label(cont->true_block()),
960 g.Label(cont->false_block()))->MarkAsControl(); 932 g.Label(cont->false_block()))->MarkAsControl();
961 } else { 933 } else {
962 ASSERT(cont->IsSet()); 934 ASSERT(cont->IsSet());
963 Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()), 935 Emit(cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()),
964 g.UseDoubleRegister(m.left().node()), 936 g.UseDoubleRegister(m.left().node()),
965 g.UseDoubleRegister(m.right().node())); 937 g.UseDoubleRegister(m.right().node()));
966 } 938 }
967 } 939 }
968 940
969 } // namespace compiler 941 } // namespace compiler
970 } // namespace internal 942 } // namespace internal
971 } // namespace v8 943 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/arm64/instruction-selector-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698