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/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/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 | 271 |
272 template <typename Matcher> | 272 template <typename Matcher> |
273 void VisitAddSub(InstructionSelector* selector, Node* node, ArchOpcode opcode, | 273 void VisitAddSub(InstructionSelector* selector, Node* node, ArchOpcode opcode, |
274 ArchOpcode negate_opcode) { | 274 ArchOpcode negate_opcode) { |
275 Arm64OperandGenerator g(selector); | 275 Arm64OperandGenerator g(selector); |
276 Matcher m(node); | 276 Matcher m(node); |
277 if (m.right().HasValue() && (m.right().Value() < 0) && | 277 if (m.right().HasValue() && (m.right().Value() < 0) && |
278 g.CanBeImmediate(-m.right().Value(), kArithmeticImm)) { | 278 g.CanBeImmediate(-m.right().Value(), kArithmeticImm)) { |
279 selector->Emit(negate_opcode, g.DefineAsRegister(node), | 279 selector->Emit(negate_opcode, g.DefineAsRegister(node), |
280 g.UseRegister(m.left().node()), | 280 g.UseRegister(m.left().node()), |
281 g.TempImmediate(-m.right().Value())); | 281 g.TempImmediate(static_cast<int32_t>(-m.right().Value()))); |
282 } else { | 282 } else { |
283 VisitBinop<Matcher>(selector, node, opcode, kArithmeticImm); | 283 VisitBinop<Matcher>(selector, node, opcode, kArithmeticImm); |
284 } | 284 } |
285 } | 285 } |
286 | 286 |
287 } // namespace | 287 } // namespace |
288 | 288 |
289 | 289 |
290 void InstructionSelector::VisitLoad(Node* node) { | 290 void InstructionSelector::VisitLoad(Node* node) { |
291 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 291 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 if (mleft.right().IsInRange(0, 63)) { | 588 if (mleft.right().IsInRange(0, 63)) { |
589 // Ubfx cannot extract bits past the register size, however since | 589 // Ubfx cannot extract bits past the register size, however since |
590 // shifting the original value would have introduced some zeros we can | 590 // shifting the original value would have introduced some zeros we can |
591 // still use ubfx with a smaller mask and the remaining bits will be | 591 // still use ubfx with a smaller mask and the remaining bits will be |
592 // zeros. | 592 // zeros. |
593 uint64_t lsb = mleft.right().Value(); | 593 uint64_t lsb = mleft.right().Value(); |
594 if (lsb + mask_width > 64) mask_width = 64 - lsb; | 594 if (lsb + mask_width > 64) mask_width = 64 - lsb; |
595 | 595 |
596 Emit(kArm64Ubfx, g.DefineAsRegister(node), | 596 Emit(kArm64Ubfx, g.DefineAsRegister(node), |
597 g.UseRegister(mleft.left().node()), | 597 g.UseRegister(mleft.left().node()), |
598 g.UseImmediate(mleft.right().node()), g.TempImmediate(mask_width)); | 598 g.UseImmediate(mleft.right().node()), |
| 599 g.TempImmediate(static_cast<int32_t>(mask_width))); |
599 return; | 600 return; |
600 } | 601 } |
601 // Other cases fall through to the normal And operation. | 602 // Other cases fall through to the normal And operation. |
602 } | 603 } |
603 } | 604 } |
604 VisitLogical<Int64BinopMatcher>( | 605 VisitLogical<Int64BinopMatcher>( |
605 this, node, &m, kArm64And, CanCover(node, m.left().node()), | 606 this, node, &m, kArm64And, CanCover(node, m.left().node()), |
606 CanCover(node, m.right().node()), kLogical64Imm); | 607 CanCover(node, m.right().node()), kLogical64Imm); |
607 } | 608 } |
608 | 609 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
724 Int64BinopMatcher mleft(m.left().node()); | 725 Int64BinopMatcher mleft(m.left().node()); |
725 if (mleft.right().HasValue()) { | 726 if (mleft.right().HasValue()) { |
726 // Select Ubfx for Shr(And(x, mask), imm) where the result of the mask is | 727 // Select Ubfx for Shr(And(x, mask), imm) where the result of the mask is |
727 // shifted into the least-significant bits. | 728 // shifted into the least-significant bits. |
728 uint64_t mask = (mleft.right().Value() >> lsb) << lsb; | 729 uint64_t mask = (mleft.right().Value() >> lsb) << lsb; |
729 uint64_t mask_width = base::bits::CountPopulation64(mask); | 730 uint64_t mask_width = base::bits::CountPopulation64(mask); |
730 uint64_t mask_msb = base::bits::CountLeadingZeros64(mask); | 731 uint64_t mask_msb = base::bits::CountLeadingZeros64(mask); |
731 if ((mask_msb + mask_width + lsb) == 64) { | 732 if ((mask_msb + mask_width + lsb) == 64) { |
732 DCHECK_EQ(lsb, base::bits::CountTrailingZeros64(mask)); | 733 DCHECK_EQ(lsb, base::bits::CountTrailingZeros64(mask)); |
733 Emit(kArm64Ubfx, g.DefineAsRegister(node), | 734 Emit(kArm64Ubfx, g.DefineAsRegister(node), |
734 g.UseRegister(mleft.left().node()), g.TempImmediate(lsb), | 735 g.UseRegister(mleft.left().node()), |
735 g.TempImmediate(mask_width)); | 736 g.TempImmediate(static_cast<int32_t>(lsb)), |
| 737 g.TempImmediate(static_cast<int32_t>(mask_width))); |
736 return; | 738 return; |
737 } | 739 } |
738 } | 740 } |
739 } | 741 } |
740 VisitRRO(this, kArm64Lsr, node, kShift64Imm); | 742 VisitRRO(this, kArm64Lsr, node, kShift64Imm); |
741 } | 743 } |
742 | 744 |
743 | 745 |
744 void InstructionSelector::VisitWord32Sar(Node* node) { | 746 void InstructionSelector::VisitWord32Sar(Node* node) { |
745 if (TryEmitBitfieldExtract32(this, node)) { | 747 if (TryEmitBitfieldExtract32(this, node)) { |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1222 VisitRR(this, kArm64Float64RoundTiesAway, node); | 1224 VisitRR(this, kArm64Float64RoundTiesAway, node); |
1223 } | 1225 } |
1224 | 1226 |
1225 | 1227 |
1226 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { | 1228 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { |
1227 Arm64OperandGenerator g(this); | 1229 Arm64OperandGenerator g(this); |
1228 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); | 1230 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); |
1229 | 1231 |
1230 FrameStateDescriptor* frame_state_descriptor = nullptr; | 1232 FrameStateDescriptor* frame_state_descriptor = nullptr; |
1231 if (descriptor->NeedsFrameState()) { | 1233 if (descriptor->NeedsFrameState()) { |
1232 frame_state_descriptor = | 1234 frame_state_descriptor = GetFrameStateDescriptor( |
1233 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); | 1235 node->InputAt(static_cast<int>(descriptor->InputCount()))); |
1234 } | 1236 } |
1235 | 1237 |
1236 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 1238 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
1237 | 1239 |
1238 // Compute InstructionOperands for inputs and outputs. | 1240 // Compute InstructionOperands for inputs and outputs. |
1239 // TODO(turbofan): on ARM64 it's probably better to use the code object in a | 1241 // TODO(turbofan): on ARM64 it's probably better to use the code object in a |
1240 // register if there are multiple uses of it. Improve constant pool and the | 1242 // register if there are multiple uses of it. Improve constant pool and the |
1241 // heuristics in the register allocator for where to emit constants. | 1243 // heuristics in the register allocator for where to emit constants. |
1242 InitializeCallBuffer(node, &buffer, true, false); | 1244 InitializeCallBuffer(node, &buffer, true, false); |
1243 | 1245 |
1244 // Push the arguments to the stack. | 1246 // Push the arguments to the stack. |
1245 bool pushed_count_uneven = buffer.pushed_nodes.size() & 1; | 1247 int aligned_push_count = static_cast<int>(buffer.pushed_nodes.size()); |
1246 int aligned_push_count = buffer.pushed_nodes.size(); | 1248 bool pushed_count_uneven = aligned_push_count & 1; |
1247 // TODO(dcarney): claim and poke probably take small immediates, | 1249 // TODO(dcarney): claim and poke probably take small immediates, |
1248 // loop here or whatever. | 1250 // loop here or whatever. |
1249 // Bump the stack pointer(s). | 1251 // Bump the stack pointer(s). |
1250 if (aligned_push_count > 0) { | 1252 if (aligned_push_count > 0) { |
1251 // TODO(dcarney): it would be better to bump the csp here only | 1253 // TODO(dcarney): it would be better to bump the csp here only |
1252 // and emit paired stores with increment for non c frames. | 1254 // and emit paired stores with increment for non c frames. |
1253 Emit(kArm64Claim, g.NoOutput(), g.TempImmediate(aligned_push_count)); | 1255 Emit(kArm64Claim, g.NoOutput(), g.TempImmediate(aligned_push_count)); |
1254 } | 1256 } |
1255 // Move arguments to the stack. | 1257 // Move arguments to the stack. |
1256 { | 1258 { |
1257 int slot = buffer.pushed_nodes.size() - 1; | 1259 int slot = aligned_push_count - 1; |
1258 // Emit the uneven pushes. | 1260 // Emit the uneven pushes. |
1259 if (pushed_count_uneven) { | 1261 if (pushed_count_uneven) { |
1260 Node* input = buffer.pushed_nodes[slot]; | 1262 Node* input = buffer.pushed_nodes[slot]; |
1261 Emit(kArm64Poke, g.NoOutput(), g.UseRegister(input), | 1263 Emit(kArm64Poke, g.NoOutput(), g.UseRegister(input), |
1262 g.TempImmediate(slot)); | 1264 g.TempImmediate(slot)); |
1263 slot--; | 1265 slot--; |
1264 } | 1266 } |
1265 // Now all pushes can be done in pairs. | 1267 // Now all pushes can be done in pairs. |
1266 for (; slot >= 0; slot -= 2) { | 1268 for (; slot >= 0; slot -= 2) { |
1267 Emit(kArm64PokePair, g.NoOutput(), | 1269 Emit(kArm64PokePair, g.NoOutput(), |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1337 return; | 1339 return; |
1338 } | 1340 } |
1339 opcode |= MiscField::encode(descriptor->flags()); | 1341 opcode |= MiscField::encode(descriptor->flags()); |
1340 | 1342 |
1341 // Emit the tailcall instruction. | 1343 // Emit the tailcall instruction. |
1342 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), | 1344 Emit(opcode, 0, nullptr, buffer.instruction_args.size(), |
1343 &buffer.instruction_args.front()); | 1345 &buffer.instruction_args.front()); |
1344 } else { | 1346 } else { |
1345 FrameStateDescriptor* frame_state_descriptor = nullptr; | 1347 FrameStateDescriptor* frame_state_descriptor = nullptr; |
1346 if (descriptor->NeedsFrameState()) { | 1348 if (descriptor->NeedsFrameState()) { |
1347 frame_state_descriptor = | 1349 frame_state_descriptor = GetFrameStateDescriptor( |
1348 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); | 1350 node->InputAt(static_cast<int>(descriptor->InputCount()))); |
1349 } | 1351 } |
1350 | 1352 |
1351 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 1353 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
1352 | 1354 |
1353 // Compute InstructionOperands for inputs and outputs. | 1355 // Compute InstructionOperands for inputs and outputs. |
1354 // TODO(turbofan): on ARM64 it's probably better to use the code object in a | 1356 // TODO(turbofan): on ARM64 it's probably better to use the code object in a |
1355 // register if there are multiple uses of it. Improve constant pool and the | 1357 // register if there are multiple uses of it. Improve constant pool and the |
1356 // heuristics in the register allocator for where to emit constants. | 1358 // heuristics in the register allocator for where to emit constants. |
1357 InitializeCallBuffer(node, &buffer, true, false); | 1359 InitializeCallBuffer(node, &buffer, true, false); |
1358 | 1360 |
1359 // Push the arguments to the stack. | 1361 // Push the arguments to the stack. |
1360 bool pushed_count_uneven = buffer.pushed_nodes.size() & 1; | 1362 int aligned_push_count = static_cast<int>(buffer.pushed_nodes.size()); |
1361 int aligned_push_count = buffer.pushed_nodes.size(); | 1363 bool pushed_count_uneven = aligned_push_count & 1; |
1362 // TODO(dcarney): claim and poke probably take small immediates, | 1364 // TODO(dcarney): claim and poke probably take small immediates, |
1363 // loop here or whatever. | 1365 // loop here or whatever. |
1364 // Bump the stack pointer(s). | 1366 // Bump the stack pointer(s). |
1365 if (aligned_push_count > 0) { | 1367 if (aligned_push_count > 0) { |
1366 // TODO(dcarney): it would be better to bump the csp here only | 1368 // TODO(dcarney): it would be better to bump the csp here only |
1367 // and emit paired stores with increment for non c frames. | 1369 // and emit paired stores with increment for non c frames. |
1368 Emit(kArm64Claim, g.NoOutput(), g.TempImmediate(aligned_push_count)); | 1370 Emit(kArm64Claim, g.NoOutput(), g.TempImmediate(aligned_push_count)); |
1369 } | 1371 } |
1370 // Move arguments to the stack. | 1372 // Move arguments to the stack. |
1371 { | 1373 { |
1372 int slot = buffer.pushed_nodes.size() - 1; | 1374 int slot = aligned_push_count - 1; |
1373 // Emit the uneven pushes. | 1375 // Emit the uneven pushes. |
1374 if (pushed_count_uneven) { | 1376 if (pushed_count_uneven) { |
1375 Node* input = buffer.pushed_nodes[slot]; | 1377 Node* input = buffer.pushed_nodes[slot]; |
1376 Emit(kArm64Poke, g.NoOutput(), g.UseRegister(input), | 1378 Emit(kArm64Poke, g.NoOutput(), g.UseRegister(input), |
1377 g.TempImmediate(slot)); | 1379 g.TempImmediate(slot)); |
1378 slot--; | 1380 slot--; |
1379 } | 1381 } |
1380 // Now all pushes can be done in pairs. | 1382 // Now all pushes can be done in pairs. |
1381 for (; slot >= 0; slot -= 2) { | 1383 for (; slot >= 0; slot -= 2) { |
1382 Emit(kArm64PokePair, g.NoOutput(), | 1384 Emit(kArm64PokePair, g.NoOutput(), |
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1898 MachineOperatorBuilder::kFloat64RoundTruncate | | 1900 MachineOperatorBuilder::kFloat64RoundTruncate | |
1899 MachineOperatorBuilder::kFloat64RoundTiesAway | | 1901 MachineOperatorBuilder::kFloat64RoundTiesAway | |
1900 MachineOperatorBuilder::kWord32ShiftIsSafe | | 1902 MachineOperatorBuilder::kWord32ShiftIsSafe | |
1901 MachineOperatorBuilder::kInt32DivIsSafe | | 1903 MachineOperatorBuilder::kInt32DivIsSafe | |
1902 MachineOperatorBuilder::kUint32DivIsSafe; | 1904 MachineOperatorBuilder::kUint32DivIsSafe; |
1903 } | 1905 } |
1904 | 1906 |
1905 } // namespace compiler | 1907 } // namespace compiler |
1906 } // namespace internal | 1908 } // namespace internal |
1907 } // namespace v8 | 1909 } // namespace v8 |
OLD | NEW |