| OLD | NEW | 
|     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  Loading... | 
|   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  Loading... | 
|   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  Loading... | 
|  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 | 
| OLD | NEW |