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 13 matching lines...) Expand all Loading... |
24 explicit MipsOperandGenerator(InstructionSelector* selector) | 24 explicit MipsOperandGenerator(InstructionSelector* selector) |
25 : OperandGenerator(selector) {} | 25 : OperandGenerator(selector) {} |
26 | 26 |
27 InstructionOperand UseOperand(Node* node, InstructionCode opcode) { | 27 InstructionOperand UseOperand(Node* node, InstructionCode opcode) { |
28 if (CanBeImmediate(node, opcode)) { | 28 if (CanBeImmediate(node, opcode)) { |
29 return UseImmediate(node); | 29 return UseImmediate(node); |
30 } | 30 } |
31 return UseRegister(node); | 31 return UseRegister(node); |
32 } | 32 } |
33 | 33 |
| 34 // Use the zero register if the node has the immediate value zero, otherwise |
| 35 // assign a register. |
| 36 InstructionOperand UseRegisterOrImmediateZero(Node* node) { |
| 37 if ((IsIntegerConstant(node) && (GetIntegerConstantValue(node) == 0)) || |
| 38 (IsFloatConstant(node) && |
| 39 (bit_cast<int64_t>(GetFloatConstantValue(node)) == V8_INT64_C(0)))) { |
| 40 return UseImmediate(node); |
| 41 } |
| 42 return UseRegister(node); |
| 43 } |
| 44 |
| 45 bool IsIntegerConstant(Node* node) { |
| 46 return (node->opcode() == IrOpcode::kInt32Constant); |
| 47 } |
| 48 |
| 49 int64_t GetIntegerConstantValue(Node* node) { |
| 50 DCHECK(node->opcode() == IrOpcode::kInt32Constant); |
| 51 return OpParameter<int32_t>(node); |
| 52 } |
| 53 |
| 54 bool IsFloatConstant(Node* node) { |
| 55 return (node->opcode() == IrOpcode::kFloat32Constant) || |
| 56 (node->opcode() == IrOpcode::kFloat64Constant); |
| 57 } |
| 58 |
| 59 double GetFloatConstantValue(Node* node) { |
| 60 if (node->opcode() == IrOpcode::kFloat32Constant) { |
| 61 return OpParameter<float>(node); |
| 62 } |
| 63 DCHECK_EQ(IrOpcode::kFloat64Constant, node->opcode()); |
| 64 return OpParameter<double>(node); |
| 65 } |
| 66 |
34 bool CanBeImmediate(Node* node, InstructionCode opcode) { | 67 bool CanBeImmediate(Node* node, InstructionCode opcode) { |
35 Int32Matcher m(node); | 68 Int32Matcher m(node); |
36 if (!m.HasValue()) return false; | 69 if (!m.HasValue()) return false; |
37 int32_t value = m.Value(); | 70 int32_t value = m.Value(); |
38 switch (ArchOpcodeField::decode(opcode)) { | 71 switch (ArchOpcodeField::decode(opcode)) { |
39 case kMipsShl: | 72 case kMipsShl: |
40 case kMipsSar: | 73 case kMipsSar: |
41 case kMipsShr: | 74 case kMipsShr: |
42 return is_uint5(value); | 75 return is_uint5(value); |
43 case kMipsAdd: | 76 case kMipsAdd: |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 break; | 326 break; |
294 case MachineRepresentation::kWord64: // Fall through. | 327 case MachineRepresentation::kWord64: // Fall through. |
295 case MachineRepresentation::kSimd128: // Fall through. | 328 case MachineRepresentation::kSimd128: // Fall through. |
296 case MachineRepresentation::kNone: | 329 case MachineRepresentation::kNone: |
297 UNREACHABLE(); | 330 UNREACHABLE(); |
298 return; | 331 return; |
299 } | 332 } |
300 | 333 |
301 if (g.CanBeImmediate(index, opcode)) { | 334 if (g.CanBeImmediate(index, opcode)) { |
302 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 335 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
303 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 336 g.UseRegister(base), g.UseImmediate(index), |
| 337 g.UseRegisterOrImmediateZero(value)); |
304 } else { | 338 } else { |
305 InstructionOperand addr_reg = g.TempRegister(); | 339 InstructionOperand addr_reg = g.TempRegister(); |
306 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, | 340 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, |
307 g.UseRegister(index), g.UseRegister(base)); | 341 g.UseRegister(index), g.UseRegister(base)); |
308 // Emit desired store opcode, using temp addr_reg. | 342 // Emit desired store opcode, using temp addr_reg. |
309 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 343 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
310 addr_reg, g.TempImmediate(0), g.UseRegister(value)); | 344 addr_reg, g.TempImmediate(0), g.UseRegisterOrImmediateZero(value)); |
311 } | 345 } |
312 } | 346 } |
313 } | 347 } |
314 | 348 |
315 | 349 |
316 void InstructionSelector::VisitWord32And(Node* node) { | 350 void InstructionSelector::VisitWord32And(Node* node) { |
317 MipsOperandGenerator g(this); | 351 MipsOperandGenerator g(this); |
318 Int32BinopMatcher m(node); | 352 Int32BinopMatcher m(node); |
319 if (m.left().IsWord32Shr() && CanCover(node, m.left().node()) && | 353 if (m.left().IsWord32Shr() && CanCover(node, m.left().node()) && |
320 m.right().HasValue()) { | 354 m.right().HasValue()) { |
(...skipping 904 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1225 break; | 1259 break; |
1226 case MachineRepresentation::kWord64: // Fall through. | 1260 case MachineRepresentation::kWord64: // Fall through. |
1227 case MachineRepresentation::kSimd128: // Fall through. | 1261 case MachineRepresentation::kSimd128: // Fall through. |
1228 case MachineRepresentation::kNone: | 1262 case MachineRepresentation::kNone: |
1229 UNREACHABLE(); | 1263 UNREACHABLE(); |
1230 return; | 1264 return; |
1231 } | 1265 } |
1232 | 1266 |
1233 if (g.CanBeImmediate(index, opcode)) { | 1267 if (g.CanBeImmediate(index, opcode)) { |
1234 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 1268 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
1235 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 1269 g.UseRegister(base), g.UseImmediate(index), |
| 1270 g.UseRegisterOrImmediateZero(value)); |
1236 } else { | 1271 } else { |
1237 InstructionOperand addr_reg = g.TempRegister(); | 1272 InstructionOperand addr_reg = g.TempRegister(); |
1238 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, | 1273 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, |
1239 g.UseRegister(index), g.UseRegister(base)); | 1274 g.UseRegister(index), g.UseRegister(base)); |
1240 // Emit desired store opcode, using temp addr_reg. | 1275 // Emit desired store opcode, using temp addr_reg. |
1241 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 1276 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
1242 addr_reg, g.TempImmediate(0), g.UseRegister(value)); | 1277 addr_reg, g.TempImmediate(0), g.UseRegisterOrImmediateZero(value)); |
1243 } | 1278 } |
1244 } | 1279 } |
1245 | 1280 |
1246 void InstructionSelector::VisitCheckedLoad(Node* node) { | 1281 void InstructionSelector::VisitCheckedLoad(Node* node) { |
1247 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); | 1282 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); |
1248 MipsOperandGenerator g(this); | 1283 MipsOperandGenerator g(this); |
1249 Node* const buffer = node->InputAt(0); | 1284 Node* const buffer = node->InputAt(0); |
1250 Node* const offset = node->InputAt(1); | 1285 Node* const offset = node->InputAt(1); |
1251 Node* const length = node->InputAt(2); | 1286 Node* const length = node->InputAt(2); |
1252 ArchOpcode opcode = kArchNop; | 1287 ArchOpcode opcode = kArchNop; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1324 ? g.UseImmediate(offset) | 1359 ? g.UseImmediate(offset) |
1325 : g.UseRegister(offset); | 1360 : g.UseRegister(offset); |
1326 | 1361 |
1327 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) | 1362 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) |
1328 ? g.CanBeImmediate(length, opcode) | 1363 ? g.CanBeImmediate(length, opcode) |
1329 ? g.UseImmediate(length) | 1364 ? g.UseImmediate(length) |
1330 : g.UseRegister(length) | 1365 : g.UseRegister(length) |
1331 : g.UseRegister(length); | 1366 : g.UseRegister(length); |
1332 | 1367 |
1333 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 1368 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
1334 offset_operand, length_operand, g.UseRegister(value), | 1369 offset_operand, length_operand, g.UseRegisterOrImmediateZero(value), |
1335 g.UseRegister(buffer)); | 1370 g.UseRegister(buffer)); |
1336 } | 1371 } |
1337 | 1372 |
1338 | 1373 |
1339 namespace { | 1374 namespace { |
1340 // Shared routine for multiple compare operations. | 1375 // Shared routine for multiple compare operations. |
1341 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1376 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1342 InstructionOperand left, InstructionOperand right, | 1377 InstructionOperand left, InstructionOperand right, |
1343 FlagsContinuation* cont) { | 1378 FlagsContinuation* cont) { |
1344 MipsOperandGenerator g(selector); | 1379 MipsOperandGenerator g(selector); |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1795 case MachineRepresentation::kWord32: | 1830 case MachineRepresentation::kWord32: |
1796 opcode = kAtomicStoreWord32; | 1831 opcode = kAtomicStoreWord32; |
1797 break; | 1832 break; |
1798 default: | 1833 default: |
1799 UNREACHABLE(); | 1834 UNREACHABLE(); |
1800 return; | 1835 return; |
1801 } | 1836 } |
1802 | 1837 |
1803 if (g.CanBeImmediate(index, opcode)) { | 1838 if (g.CanBeImmediate(index, opcode)) { |
1804 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 1839 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
1805 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 1840 g.UseRegister(base), g.UseImmediate(index), |
| 1841 g.UseRegisterOrImmediateZero(value)); |
1806 } else { | 1842 } else { |
1807 InstructionOperand addr_reg = g.TempRegister(); | 1843 InstructionOperand addr_reg = g.TempRegister(); |
1808 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, | 1844 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, |
1809 g.UseRegister(index), g.UseRegister(base)); | 1845 g.UseRegister(index), g.UseRegister(base)); |
1810 // Emit desired store opcode, using temp addr_reg. | 1846 // Emit desired store opcode, using temp addr_reg. |
1811 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 1847 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
1812 addr_reg, g.TempImmediate(0), g.UseRegister(value)); | 1848 addr_reg, g.TempImmediate(0), g.UseRegisterOrImmediateZero(value)); |
1813 } | 1849 } |
1814 } | 1850 } |
1815 | 1851 |
1816 // static | 1852 // static |
1817 MachineOperatorBuilder::Flags | 1853 MachineOperatorBuilder::Flags |
1818 InstructionSelector::SupportedMachineOperatorFlags() { | 1854 InstructionSelector::SupportedMachineOperatorFlags() { |
1819 MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags; | 1855 MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags; |
1820 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && | 1856 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && |
1821 IsFp64Mode()) { | 1857 IsFp64Mode()) { |
1822 flags |= MachineOperatorBuilder::kFloat64RoundDown | | 1858 flags |= MachineOperatorBuilder::kFloat64RoundDown | |
(...skipping 25 matching lines...) Expand all Loading... |
1848 DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) || | 1884 DCHECK(IsMipsArchVariant(kLoongson) || IsMipsArchVariant(kMips32r1) || |
1849 IsMipsArchVariant(kMips32r2)); | 1885 IsMipsArchVariant(kMips32r2)); |
1850 return MachineOperatorBuilder::AlignmentRequirements:: | 1886 return MachineOperatorBuilder::AlignmentRequirements:: |
1851 NoUnalignedAccessSupport(); | 1887 NoUnalignedAccessSupport(); |
1852 } | 1888 } |
1853 } | 1889 } |
1854 | 1890 |
1855 } // namespace compiler | 1891 } // namespace compiler |
1856 } // namespace internal | 1892 } // namespace internal |
1857 } // namespace v8 | 1893 } // namespace v8 |
OLD | NEW |