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

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

Issue 1779713009: Implement optional turbofan UnalignedLoad and UnalignedStore operators (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Unaligned access simulate using load/shift/or and store/shift/and Created 4 years, 8 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 "src/base/adapters.h" 5 #include "src/base/adapters.h"
6 #include "src/base/bits.h" 6 #include "src/base/bits.h"
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 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 Emit(kMipsIns, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()), 300 Emit(kMipsIns, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
301 g.TempImmediate(0), g.TempImmediate(shift)); 301 g.TempImmediate(0), g.TempImmediate(shift));
302 return; 302 return;
303 } 303 }
304 } 304 }
305 VisitBinop(this, node, kMipsAnd); 305 VisitBinop(this, node, kMipsAnd);
306 } 306 }
307 307
308 308
309 void InstructionSelector::VisitWord32Or(Node* node) { 309 void InstructionSelector::VisitWord32Or(Node* node) {
310 Int32BinopMatcher orm(node);
311
312 bool unalignedMatched = false;
313 bool loadSigned = false;
314
315 int i = 0;
316 uintptr_t prevAddress = 0;
317 Node* smallestLoad = NULL;
318
319 // Unligned access is simulated using combinations of
320 // load byte, shift and or operations, like this
321 // Result = 0
322 // Result = LoadByte (high) | Result << 8
323 // Result = LoadByte (high - 1) | Result << 8
324 // ...
325 // Result = LoadByte (low) | Result << 8
326 // We are trying to match the graph that corresponds
327 // to the above operations and reduce it to
328 // one simple Unaligned load
329 while (orm.left().IsWord32Shl() && orm.right().IsLoad()) {
330 Int32BinopMatcher shl(orm.left().node());
331 LoadMatcher<PtrMatcher> load(orm.right().node());
332
333 // Verifying load address
334 if (load.object().HasValue()) {
335 // Assumption is that the first byte will
336 // always be the most significant
337 if (prevAddress == 0) {
338 prevAddress = load.object().Value();
339 smallestLoad = load.node();
340 } else {
341 // Verifying that load addresses are consecutive
342 if (prevAddress + 1 != load.object().Value()) {
343 unalignedMatched = false;
344 break;
345 }
346 prevAddress = load.object().Value();
347 loadSigned = LoadRepresentationOf(load.node()->op()).IsSigned();
348 }
349 } else {
350 unalignedMatched = false;
351 break;
352 }
353
354 if (shl.left().IsWord32Or() && shl.right().Is(8)) {
355 orm = Int32BinopMatcher(shl.left().node());
356 } else if (shl.left().Is(0)) {
357 unalignedMatched = true;
358 break;
359 } else {
360 unalignedMatched = false;
361 break;
362 }
363
364 i++;
365 // Something is not right, the graph is too deep, break
366 if (i > 8) {
367 unalignedMatched = false;
368 break;
369 }
370 }
371
372 if (unalignedMatched) {
373 MipsOperandGenerator g(this);
374 ArchOpcode opcode = kArchNop;
375
376 if (i == 3) {
377 opcode = kMipsUlw;
378 } else if (i == 1) {
379 opcode = loadSigned ? kMipsUlh : kMipsUlhu;
380 } else {
381 unalignedMatched = false;
382 }
383
384 if (unalignedMatched) {
385 MipsOperandGenerator g(this);
386
387 DCHECK(smallestLoad != NULL);
388
389 Node* base = smallestLoad->InputAt(0);
390 Node* index = smallestLoad->InputAt(1);
391
392 if (g.CanBeImmediate(index, opcode)) {
393 Emit(opcode | AddressingModeField::encode(kMode_MRI),
394 g.DefineAsRegister(node), g.UseRegister(base),
395 g.UseImmediate(index));
396 } else {
397 InstructionOperand addr_reg = g.TempRegister();
398 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg,
399 g.UseRegister(index), g.UseRegister(base));
400 // Emit desired load opcode, using temp addr_reg.
401 Emit(opcode | AddressingModeField::encode(kMode_MRI),
402 g.DefineAsRegister(node), addr_reg, g.TempImmediate(0));
403 }
404 return;
405 }
406 }
407
310 VisitBinop(this, node, kMipsOr); 408 VisitBinop(this, node, kMipsOr);
311 } 409 }
312 410
313 411
314 void InstructionSelector::VisitWord32Xor(Node* node) { 412 void InstructionSelector::VisitWord32Xor(Node* node) {
315 Int32BinopMatcher m(node); 413 Int32BinopMatcher m(node);
316 if (m.left().IsWord32Or() && CanCover(node, m.left().node()) && 414 if (m.left().IsWord32Or() && CanCover(node, m.left().node()) &&
317 m.right().Is(-1)) { 415 m.right().Is(-1)) {
318 Int32BinopMatcher mleft(m.left().node()); 416 Int32BinopMatcher mleft(m.left().node());
319 if (!mleft.right().HasValue()) { 417 if (!mleft.right().HasValue()) {
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after
965 } 1063 }
966 } 1064 }
967 } 1065 }
968 } 1066 }
969 1067
970 1068
971 bool InstructionSelector::IsTailCallAddressImmediate() { return false; } 1069 bool InstructionSelector::IsTailCallAddressImmediate() { return false; }
972 1070
973 int InstructionSelector::GetTempsCountForTailCallFromJSFunction() { return 3; } 1071 int InstructionSelector::GetTempsCountForTailCallFromJSFunction() { return 3; }
974 1072
1073 void InstructionSelector::VisitUnalignedLoad(Node* node) {
1074 UnalignedLoadRepresentation load_rep =
1075 UnalignedLoadRepresentationOf(node->op());
1076 MipsOperandGenerator g(this);
1077 Node* base = node->InputAt(0);
1078 Node* index = node->InputAt(1);
1079
1080 ArchOpcode opcode = kArchNop;
1081 switch (load_rep.representation()) {
1082 case MachineRepresentation::kBit: // Fall through.
1083 case MachineRepresentation::kWord8:
1084 opcode = load_rep.IsUnsigned() ? kMipsLbu : kMipsLb;
1085 break;
1086 case MachineRepresentation::kWord16:
1087 opcode = load_rep.IsUnsigned() ? kMipsUlhu : kMipsUlh;
1088 break;
1089 case MachineRepresentation::kTagged: // Fall through.
1090 case MachineRepresentation::kWord32:
1091 opcode = kMipsUlw;
1092 break;
1093 case MachineRepresentation::kFloat32:
1094 opcode = kMipsUlwc1;
1095 break;
1096 case MachineRepresentation::kFloat64:
1097 opcode = kMipsUldc1;
1098 break;
1099 case MachineRepresentation::kWord64: // Fall through.
1100 case MachineRepresentation::kSimd128: // Fall through.
1101 case MachineRepresentation::kNone:
1102 UNREACHABLE();
1103 return;
1104 }
1105
1106 if (g.CanBeImmediate(index, opcode)) {
1107 Emit(opcode | AddressingModeField::encode(kMode_MRI),
1108 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
1109 } else {
1110 InstructionOperand addr_reg = g.TempRegister();
1111 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg,
1112 g.UseRegister(index), g.UseRegister(base));
1113 // Emit desired load opcode, using temp addr_reg.
1114 Emit(opcode | AddressingModeField::encode(kMode_MRI),
1115 g.DefineAsRegister(node), addr_reg, g.TempImmediate(0));
1116 }
1117 }
1118
1119 void InstructionSelector::VisitUnalignedStore(Node* node) {
1120 MipsOperandGenerator g(this);
1121 Node* base = node->InputAt(0);
1122 Node* index = node->InputAt(1);
1123 Node* value = node->InputAt(2);
1124
1125 UnalignedStoreRepresentation rep = UnalignedStoreRepresentationOf(node->op());
1126
1127 // TODO(mips): I guess this could be done in a better way.
1128 ArchOpcode opcode = kArchNop;
1129 switch (rep) {
1130 case MachineRepresentation::kFloat32:
1131 opcode = kMipsUswc1;
1132 break;
1133 case MachineRepresentation::kFloat64:
1134 opcode = kMipsUsdc1;
1135 break;
1136 case MachineRepresentation::kBit: // Fall through.
1137 case MachineRepresentation::kWord8:
1138 opcode = kMipsSb;
1139 break;
1140 case MachineRepresentation::kWord16:
1141 opcode = kMipsUsh;
1142 break;
1143 case MachineRepresentation::kTagged: // Fall through.
1144 case MachineRepresentation::kWord32:
1145 opcode = kMipsUsw;
1146 break;
1147 case MachineRepresentation::kWord64: // Fall through.
1148 case MachineRepresentation::kSimd128: // Fall through.
1149 case MachineRepresentation::kNone:
1150 UNREACHABLE();
1151 return;
1152 }
1153
1154 if (g.CanBeImmediate(index, opcode)) {
1155 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
1156 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
1157 } else {
1158 InstructionOperand addr_reg = g.TempRegister();
1159 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg,
1160 g.UseRegister(index), g.UseRegister(base));
1161 // Emit desired store opcode, using temp addr_reg.
1162 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
1163 addr_reg, g.TempImmediate(0), g.UseRegister(value));
1164 }
1165 }
1166
975 void InstructionSelector::VisitCheckedLoad(Node* node) { 1167 void InstructionSelector::VisitCheckedLoad(Node* node) {
976 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); 1168 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op());
977 MipsOperandGenerator g(this); 1169 MipsOperandGenerator g(this);
978 Node* const buffer = node->InputAt(0); 1170 Node* const buffer = node->InputAt(0);
979 Node* const offset = node->InputAt(1); 1171 Node* const offset = node->InputAt(1);
980 Node* const length = node->InputAt(2); 1172 Node* const length = node->InputAt(2);
981 ArchOpcode opcode = kArchNop; 1173 ArchOpcode opcode = kArchNop;
982 switch (load_rep.representation()) { 1174 switch (load_rep.representation()) {
983 case MachineRepresentation::kWord8: 1175 case MachineRepresentation::kWord8:
984 opcode = load_rep.IsSigned() ? kCheckedLoadInt8 : kCheckedLoadUint8; 1176 opcode = load_rep.IsSigned() ? kCheckedLoadInt8 : kCheckedLoadUint8;
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
1457 MachineOperatorBuilder::Flags 1649 MachineOperatorBuilder::Flags
1458 InstructionSelector::SupportedMachineOperatorFlags() { 1650 InstructionSelector::SupportedMachineOperatorFlags() {
1459 MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags; 1651 MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags;
1460 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 1652 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
1461 IsFp64Mode()) { 1653 IsFp64Mode()) {
1462 flags |= MachineOperatorBuilder::kFloat64RoundDown | 1654 flags |= MachineOperatorBuilder::kFloat64RoundDown |
1463 MachineOperatorBuilder::kFloat64RoundUp | 1655 MachineOperatorBuilder::kFloat64RoundUp |
1464 MachineOperatorBuilder::kFloat64RoundTruncate | 1656 MachineOperatorBuilder::kFloat64RoundTruncate |
1465 MachineOperatorBuilder::kFloat64RoundTiesEven; 1657 MachineOperatorBuilder::kFloat64RoundTiesEven;
1466 } 1658 }
1659
1660 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r1)) ||
1661 IsMipsArchVariant(kLoongson)) {
1662 flags |= MachineOperatorBuilder::kUnalignedLoad |
1663 MachineOperatorBuilder::kUnalignedStore;
1664 }
1665
1467 return flags | MachineOperatorBuilder::kWord32Ctz | 1666 return flags | MachineOperatorBuilder::kWord32Ctz |
1468 MachineOperatorBuilder::kWord32Popcnt | 1667 MachineOperatorBuilder::kWord32Popcnt |
1469 MachineOperatorBuilder::kInt32DivIsSafe | 1668 MachineOperatorBuilder::kInt32DivIsSafe |
1470 MachineOperatorBuilder::kUint32DivIsSafe | 1669 MachineOperatorBuilder::kUint32DivIsSafe |
1471 MachineOperatorBuilder::kWord32ShiftIsSafe | 1670 MachineOperatorBuilder::kWord32ShiftIsSafe |
1472 MachineOperatorBuilder::kFloat64Min | 1671 MachineOperatorBuilder::kFloat64Min |
1473 MachineOperatorBuilder::kFloat64Max | 1672 MachineOperatorBuilder::kFloat64Max |
1474 MachineOperatorBuilder::kFloat32Min | 1673 MachineOperatorBuilder::kFloat32Min |
1475 MachineOperatorBuilder::kFloat32Max | 1674 MachineOperatorBuilder::kFloat32Max |
1476 MachineOperatorBuilder::kFloat32RoundDown | 1675 MachineOperatorBuilder::kFloat32RoundDown |
1477 MachineOperatorBuilder::kFloat32RoundUp | 1676 MachineOperatorBuilder::kFloat32RoundUp |
1478 MachineOperatorBuilder::kFloat32RoundTruncate | 1677 MachineOperatorBuilder::kFloat32RoundTruncate |
1479 MachineOperatorBuilder::kFloat32RoundTiesEven; 1678 MachineOperatorBuilder::kFloat32RoundTiesEven;
1480 } 1679 }
1481 1680
1482 } // namespace compiler 1681 } // namespace compiler
1483 } // namespace internal 1682 } // namespace internal
1484 } // namespace v8 1683 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698