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

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

Issue 989203002: [x86] Faster/shorter code for stack checks. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 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
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 <algorithm> 5 #include <algorithm>
6 6
7 #include "src/compiler/instruction-selector-impl.h" 7 #include "src/compiler/instruction-selector-impl.h"
8 #include "src/compiler/node-matchers.h" 8 #include "src/compiler/node-matchers.h"
9 #include "src/compiler/node-properties.h" 9 #include "src/compiler/node-properties.h"
10 10
(...skipping 969 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 // Emit the call instruction. 980 // Emit the call instruction.
981 InstructionOperand* first_output = 981 InstructionOperand* first_output =
982 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; 982 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
983 Instruction* call_instr = 983 Instruction* call_instr =
984 Emit(opcode, buffer.outputs.size(), first_output, 984 Emit(opcode, buffer.outputs.size(), first_output,
985 buffer.instruction_args.size(), &buffer.instruction_args.front()); 985 buffer.instruction_args.size(), &buffer.instruction_args.front());
986 call_instr->MarkAsCall(); 986 call_instr->MarkAsCall();
987 } 987 }
988 988
989 989
990 namespace {
991
990 // Shared routine for multiple compare operations. 992 // Shared routine for multiple compare operations.
991 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, 993 void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
992 InstructionOperand left, InstructionOperand right, 994 InstructionOperand left, InstructionOperand right,
993 FlagsContinuation* cont) { 995 FlagsContinuation* cont) {
994 X64OperandGenerator g(selector); 996 X64OperandGenerator g(selector);
995 opcode = cont->Encode(opcode); 997 opcode = cont->Encode(opcode);
996 if (cont->IsBranch()) { 998 if (cont->IsBranch()) {
997 selector->Emit(opcode, g.NoOutput(), left, right, 999 selector->Emit(opcode, g.NoOutput(), left, right,
998 g.Label(cont->true_block()), 1000 g.Label(cont->true_block()),
999 g.Label(cont->false_block()))->MarkAsControl(); 1001 g.Label(cont->false_block()))->MarkAsControl();
1000 } else { 1002 } else {
1001 DCHECK(cont->IsSet()); 1003 DCHECK(cont->IsSet());
1002 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); 1004 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right);
1003 } 1005 }
1004 } 1006 }
1005 1007
1006 1008
1007 // Shared routine for multiple compare operations. 1009 // Shared routine for multiple compare operations.
1008 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, 1010 void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
1009 Node* left, Node* right, FlagsContinuation* cont, 1011 Node* left, Node* right, FlagsContinuation* cont,
1010 bool commutative) { 1012 bool commutative) {
1011 X64OperandGenerator g(selector); 1013 X64OperandGenerator g(selector);
1012 if (commutative && g.CanBeBetterLeftOperand(right)) { 1014 if (commutative && g.CanBeBetterLeftOperand(right)) {
1013 std::swap(left, right); 1015 std::swap(left, right);
1014 } 1016 }
1015 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont); 1017 VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont);
1016 } 1018 }
1017 1019
1018 1020
1019 // Shared routine for multiple word compare operations. 1021 // Shared routine for multiple word compare operations.
1020 static void VisitWordCompare(InstructionSelector* selector, Node* node, 1022 void VisitWordCompare(InstructionSelector* selector, Node* node,
1021 InstructionCode opcode, FlagsContinuation* cont) { 1023 InstructionCode opcode, FlagsContinuation* cont) {
1022 X64OperandGenerator g(selector); 1024 X64OperandGenerator g(selector);
1023 Node* const left = node->InputAt(0); 1025 Node* const left = node->InputAt(0);
1024 Node* const right = node->InputAt(1); 1026 Node* const right = node->InputAt(1);
1025 1027
1026 // Match immediates on left or right side of comparison. 1028 // Match immediates on left or right side of comparison.
1027 if (g.CanBeImmediate(right)) { 1029 if (g.CanBeImmediate(right)) {
1028 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont); 1030 VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont);
1029 } else if (g.CanBeImmediate(left)) { 1031 } else if (g.CanBeImmediate(left)) {
1030 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); 1032 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
1031 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont); 1033 VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont);
1032 } else { 1034 } else {
1033 VisitCompare(selector, opcode, left, right, cont, 1035 VisitCompare(selector, opcode, left, right, cont,
1034 node->op()->HasProperty(Operator::kCommutative)); 1036 node->op()->HasProperty(Operator::kCommutative));
1035 } 1037 }
1036 } 1038 }
1037 1039
1038 1040
1041 // Shared routine for 64-bit word comparison operations.
1042 void VisitWord64Compare(InstructionSelector* selector, Node* node,
1043 FlagsContinuation* cont) {
1044 X64OperandGenerator g(selector);
1045 Int64BinopMatcher m(node);
1046 if (m.left().IsLoad() && m.right().IsLoadStackPointer()) {
1047 LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node());
1048 ExternalReference js_stack_limit =
1049 ExternalReference::address_of_stack_limit(selector->isolate());
1050 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) {
1051 // Compare(Load(js_stack_limit), LoadStackPointer)
1052 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
1053 InstructionCode opcode = cont->Encode(kX64StackCheck);
1054 if (cont->IsBranch()) {
1055 selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()),
1056 g.Label(cont->false_block()))->MarkAsControl();
1057 } else {
1058 DCHECK(cont->IsSet());
1059 selector->Emit(opcode, g.DefineAsRegister(cont->result()));
1060 }
1061 return;
1062 }
1063 }
1064 VisitWordCompare(selector, node, kX64Cmp, cont);
1065 }
1066
1067
1039 // Shared routine for comparison with zero. 1068 // Shared routine for comparison with zero.
1040 static void VisitCompareZero(InstructionSelector* selector, Node* node, 1069 void VisitCompareZero(InstructionSelector* selector, Node* node,
1041 InstructionCode opcode, FlagsContinuation* cont) { 1070 InstructionCode opcode, FlagsContinuation* cont) {
1042 X64OperandGenerator g(selector); 1071 X64OperandGenerator g(selector);
1043 VisitCompare(selector, opcode, g.Use(node), g.TempImmediate(0), cont); 1072 VisitCompare(selector, opcode, g.Use(node), g.TempImmediate(0), cont);
1044 } 1073 }
1045 1074
1046 1075
1047 // Shared routine for multiple float64 compare operations (inputs commuted). 1076 // Shared routine for multiple float64 compare operations (inputs commuted).
1048 static void VisitFloat64Compare(InstructionSelector* selector, Node* node, 1077 void VisitFloat64Compare(InstructionSelector* selector, Node* node,
1049 FlagsContinuation* cont) { 1078 FlagsContinuation* cont) {
1050 Node* const left = node->InputAt(0); 1079 Node* const left = node->InputAt(0);
1051 Node* const right = node->InputAt(1); 1080 Node* const right = node->InputAt(1);
1052 VisitCompare(selector, kSSEFloat64Cmp, right, left, cont, false); 1081 VisitCompare(selector, kSSEFloat64Cmp, right, left, cont, false);
1053 } 1082 }
1054 1083
1084 } // namespace
1085
1055 1086
1056 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, 1087 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
1057 BasicBlock* fbranch) { 1088 BasicBlock* fbranch) {
1058 X64OperandGenerator g(this); 1089 X64OperandGenerator g(this);
1059 Node* user = branch; 1090 Node* user = branch;
1060 Node* value = branch->InputAt(0); 1091 Node* value = branch->InputAt(0);
1061 1092
1062 FlagsContinuation cont(kNotEqual, tbranch, fbranch); 1093 FlagsContinuation cont(kNotEqual, tbranch, fbranch);
1063 1094
1064 // Try to combine with comparisons against 0 by simply inverting the branch. 1095 // Try to combine with comparisons against 0 by simply inverting the branch.
(...skipping 21 matching lines...) Expand all
1086 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); 1117 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
1087 return VisitWordCompare(this, value, kX64Cmp32, &cont); 1118 return VisitWordCompare(this, value, kX64Cmp32, &cont);
1088 case IrOpcode::kUint32LessThan: 1119 case IrOpcode::kUint32LessThan:
1089 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); 1120 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
1090 return VisitWordCompare(this, value, kX64Cmp32, &cont); 1121 return VisitWordCompare(this, value, kX64Cmp32, &cont);
1091 case IrOpcode::kUint32LessThanOrEqual: 1122 case IrOpcode::kUint32LessThanOrEqual:
1092 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); 1123 cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
1093 return VisitWordCompare(this, value, kX64Cmp32, &cont); 1124 return VisitWordCompare(this, value, kX64Cmp32, &cont);
1094 case IrOpcode::kWord64Equal: 1125 case IrOpcode::kWord64Equal:
1095 cont.OverwriteAndNegateIfEqual(kEqual); 1126 cont.OverwriteAndNegateIfEqual(kEqual);
1096 return VisitWordCompare(this, value, kX64Cmp, &cont); 1127 return VisitWord64Compare(this, value, &cont);
1097 case IrOpcode::kInt64LessThan: 1128 case IrOpcode::kInt64LessThan:
1098 cont.OverwriteAndNegateIfEqual(kSignedLessThan); 1129 cont.OverwriteAndNegateIfEqual(kSignedLessThan);
1099 return VisitWordCompare(this, value, kX64Cmp, &cont); 1130 return VisitWord64Compare(this, value, &cont);
1100 case IrOpcode::kInt64LessThanOrEqual: 1131 case IrOpcode::kInt64LessThanOrEqual:
1101 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); 1132 cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
1102 return VisitWordCompare(this, value, kX64Cmp, &cont); 1133 return VisitWord64Compare(this, value, &cont);
1103 case IrOpcode::kUint64LessThan: 1134 case IrOpcode::kUint64LessThan:
1104 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); 1135 cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
1105 return VisitWordCompare(this, value, kX64Cmp, &cont); 1136 return VisitWord64Compare(this, value, &cont);
1106 case IrOpcode::kFloat64Equal: 1137 case IrOpcode::kFloat64Equal:
1107 cont.OverwriteAndNegateIfEqual(kUnorderedEqual); 1138 cont.OverwriteAndNegateIfEqual(kUnorderedEqual);
1108 return VisitFloat64Compare(this, value, &cont); 1139 return VisitFloat64Compare(this, value, &cont);
1109 case IrOpcode::kFloat64LessThan: 1140 case IrOpcode::kFloat64LessThan:
1110 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThan); 1141 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
1111 return VisitFloat64Compare(this, value, &cont); 1142 return VisitFloat64Compare(this, value, &cont);
1112 case IrOpcode::kFloat64LessThanOrEqual: 1143 case IrOpcode::kFloat64LessThanOrEqual:
1113 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual); 1144 cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
1114 return VisitFloat64Compare(this, value, &cont); 1145 return VisitFloat64Compare(this, value, &cont);
1115 case IrOpcode::kProjection: 1146 case IrOpcode::kProjection:
(...skipping 17 matching lines...) Expand all
1133 return VisitBinop(this, node, kX64Sub32, &cont); 1164 return VisitBinop(this, node, kX64Sub32, &cont);
1134 default: 1165 default:
1135 break; 1166 break;
1136 } 1167 }
1137 } 1168 }
1138 } 1169 }
1139 break; 1170 break;
1140 case IrOpcode::kInt32Sub: 1171 case IrOpcode::kInt32Sub:
1141 return VisitWordCompare(this, value, kX64Cmp32, &cont); 1172 return VisitWordCompare(this, value, kX64Cmp32, &cont);
1142 case IrOpcode::kInt64Sub: 1173 case IrOpcode::kInt64Sub:
1143 return VisitWordCompare(this, value, kX64Cmp, &cont); 1174 return VisitWord64Compare(this, value, &cont);
1144 case IrOpcode::kWord32And: 1175 case IrOpcode::kWord32And:
1145 return VisitWordCompare(this, value, kX64Test32, &cont); 1176 return VisitWordCompare(this, value, kX64Test32, &cont);
1146 case IrOpcode::kWord64And: 1177 case IrOpcode::kWord64And:
1147 return VisitWordCompare(this, value, kX64Test, &cont); 1178 return VisitWordCompare(this, value, kX64Test, &cont);
1148 default: 1179 default:
1149 break; 1180 break;
1150 } 1181 }
1151 } 1182 }
1152 1183
1153 // Branch could not be combined with a compare, emit compare against 0. 1184 // Branch could not be combined with a compare, emit compare against 0.
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 cont.Negate(); 1326 cont.Negate();
1296 } else { 1327 } else {
1297 break; 1328 break;
1298 } 1329 }
1299 } 1330 }
1300 1331
1301 // Try to combine the branch with a comparison. 1332 // Try to combine the branch with a comparison.
1302 if (CanCover(user, value)) { 1333 if (CanCover(user, value)) {
1303 switch (value->opcode()) { 1334 switch (value->opcode()) {
1304 case IrOpcode::kInt64Sub: 1335 case IrOpcode::kInt64Sub:
1305 return VisitWordCompare(this, value, kX64Cmp, &cont); 1336 return VisitWord64Compare(this, value, &cont);
1306 case IrOpcode::kWord64And: 1337 case IrOpcode::kWord64And:
1307 return VisitWordCompare(this, value, kX64Test, &cont); 1338 return VisitWordCompare(this, value, kX64Test, &cont);
1308 default: 1339 default:
1309 break; 1340 break;
1310 } 1341 }
1311 } 1342 }
1312 return VisitCompareZero(this, value, kX64Cmp, &cont); 1343 return VisitCompareZero(this, value, kX64Cmp, &cont);
1313 } 1344 }
1314 VisitWordCompare(this, node, kX64Cmp, &cont); 1345 VisitWord64Compare(this, node, &cont);
1315 } 1346 }
1316 1347
1317 1348
1318 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) { 1349 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
1319 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { 1350 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1320 FlagsContinuation cont(kOverflow, ovf); 1351 FlagsContinuation cont(kOverflow, ovf);
1321 VisitBinop(this, node, kX64Add32, &cont); 1352 VisitBinop(this, node, kX64Add32, &cont);
1322 } 1353 }
1323 FlagsContinuation cont; 1354 FlagsContinuation cont;
1324 VisitBinop(this, node, kX64Add32, &cont); 1355 VisitBinop(this, node, kX64Add32, &cont);
1325 } 1356 }
1326 1357
1327 1358
1328 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { 1359 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
1329 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { 1360 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1330 FlagsContinuation cont(kOverflow, ovf); 1361 FlagsContinuation cont(kOverflow, ovf);
1331 return VisitBinop(this, node, kX64Sub32, &cont); 1362 return VisitBinop(this, node, kX64Sub32, &cont);
1332 } 1363 }
1333 FlagsContinuation cont; 1364 FlagsContinuation cont;
1334 VisitBinop(this, node, kX64Sub32, &cont); 1365 VisitBinop(this, node, kX64Sub32, &cont);
1335 } 1366 }
1336 1367
1337 1368
1338 void InstructionSelector::VisitInt64LessThan(Node* node) { 1369 void InstructionSelector::VisitInt64LessThan(Node* node) {
1339 FlagsContinuation cont(kSignedLessThan, node); 1370 FlagsContinuation cont(kSignedLessThan, node);
1340 VisitWordCompare(this, node, kX64Cmp, &cont); 1371 VisitWord64Compare(this, node, &cont);
1341 } 1372 }
1342 1373
1343 1374
1344 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) { 1375 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) {
1345 FlagsContinuation cont(kSignedLessThanOrEqual, node); 1376 FlagsContinuation cont(kSignedLessThanOrEqual, node);
1346 VisitWordCompare(this, node, kX64Cmp, &cont); 1377 VisitWord64Compare(this, node, &cont);
1347 } 1378 }
1348 1379
1349 1380
1350 void InstructionSelector::VisitUint64LessThan(Node* node) { 1381 void InstructionSelector::VisitUint64LessThan(Node* node) {
1351 FlagsContinuation cont(kUnsignedLessThan, node); 1382 FlagsContinuation cont(kUnsignedLessThan, node);
1352 VisitWordCompare(this, node, kX64Cmp, &cont); 1383 VisitWord64Compare(this, node, &cont);
1353 } 1384 }
1354 1385
1355 1386
1356 void InstructionSelector::VisitFloat64Equal(Node* node) { 1387 void InstructionSelector::VisitFloat64Equal(Node* node) {
1357 FlagsContinuation cont(kUnorderedEqual, node); 1388 FlagsContinuation cont(kUnorderedEqual, node);
1358 VisitFloat64Compare(this, node, &cont); 1389 VisitFloat64Compare(this, node, &cont);
1359 } 1390 }
1360 1391
1361 1392
1362 void InstructionSelector::VisitFloat64LessThan(Node* node) { 1393 void InstructionSelector::VisitFloat64LessThan(Node* node) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 flags |= MachineOperatorBuilder::kFloat64Floor | 1448 flags |= MachineOperatorBuilder::kFloat64Floor |
1418 MachineOperatorBuilder::kFloat64Ceil | 1449 MachineOperatorBuilder::kFloat64Ceil |
1419 MachineOperatorBuilder::kFloat64RoundTruncate; 1450 MachineOperatorBuilder::kFloat64RoundTruncate;
1420 } 1451 }
1421 return flags; 1452 return flags;
1422 } 1453 }
1423 1454
1424 } // namespace compiler 1455 } // namespace compiler
1425 } // namespace internal 1456 } // namespace internal
1426 } // namespace v8 1457 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/x64/instruction-codes-x64.h ('k') | test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698