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 12 matching lines...) Expand all Loading... |
23 kNoImmediate | 23 kNoImmediate |
24 }; | 24 }; |
25 | 25 |
26 | 26 |
27 // Adds Arm64-specific methods for generating operands. | 27 // Adds Arm64-specific methods for generating operands. |
28 class Arm64OperandGenerator FINAL : public OperandGenerator { | 28 class Arm64OperandGenerator FINAL : public OperandGenerator { |
29 public: | 29 public: |
30 explicit Arm64OperandGenerator(InstructionSelector* selector) | 30 explicit Arm64OperandGenerator(InstructionSelector* selector) |
31 : OperandGenerator(selector) {} | 31 : OperandGenerator(selector) {} |
32 | 32 |
33 InstructionOperand* UseOperand(Node* node, ImmediateMode mode) { | 33 InstructionOperand UseOperand(Node* node, ImmediateMode mode) { |
34 if (CanBeImmediate(node, mode)) { | 34 if (CanBeImmediate(node, mode)) { |
35 return UseImmediate(node); | 35 return UseImmediate(node); |
36 } | 36 } |
37 return UseRegister(node); | 37 return UseRegister(node); |
38 } | 38 } |
39 | 39 |
40 bool CanBeImmediate(Node* node, ImmediateMode mode) { | 40 bool CanBeImmediate(Node* node, ImmediateMode mode) { |
41 int64_t value; | 41 int64_t value; |
42 if (node->opcode() == IrOpcode::kInt32Constant) | 42 if (node->opcode() == IrOpcode::kInt32Constant) |
43 value = OpParameter<int32_t>(node); | 43 value = OpParameter<int32_t>(node); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 } | 167 } |
168 | 168 |
169 | 169 |
170 // Shared routine for multiple binary operations. | 170 // Shared routine for multiple binary operations. |
171 template <typename Matcher> | 171 template <typename Matcher> |
172 static void VisitBinop(InstructionSelector* selector, Node* node, | 172 static void VisitBinop(InstructionSelector* selector, Node* node, |
173 InstructionCode opcode, ImmediateMode operand_mode, | 173 InstructionCode opcode, ImmediateMode operand_mode, |
174 FlagsContinuation* cont) { | 174 FlagsContinuation* cont) { |
175 Arm64OperandGenerator g(selector); | 175 Arm64OperandGenerator g(selector); |
176 Matcher m(node); | 176 Matcher m(node); |
177 InstructionOperand* inputs[4]; | 177 InstructionOperand inputs[4]; |
178 size_t input_count = 0; | 178 size_t input_count = 0; |
179 InstructionOperand* outputs[2]; | 179 InstructionOperand outputs[2]; |
180 size_t output_count = 0; | 180 size_t output_count = 0; |
181 bool try_ror_operand = true; | 181 bool try_ror_operand = true; |
182 | 182 |
183 if (m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() || m.IsInt64Sub()) { | 183 if (m.IsInt32Add() || m.IsInt64Add() || m.IsInt32Sub() || m.IsInt64Sub()) { |
184 try_ror_operand = false; | 184 try_ror_operand = false; |
185 } | 185 } |
186 | 186 |
187 if (g.CanBeImmediate(m.right().node(), operand_mode)) { | 187 if (g.CanBeImmediate(m.right().node(), operand_mode)) { |
188 inputs[input_count++] = g.UseRegister(m.left().node()); | 188 inputs[input_count++] = g.UseRegister(m.left().node()); |
189 inputs[input_count++] = g.UseImmediate(m.right().node()); | 189 inputs[input_count++] = g.UseImmediate(m.right().node()); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 Node* index = node->InputAt(1); | 306 Node* index = node->InputAt(1); |
307 Node* value = node->InputAt(2); | 307 Node* value = node->InputAt(2); |
308 | 308 |
309 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); | 309 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); |
310 MachineType rep = RepresentationOf(store_rep.machine_type()); | 310 MachineType rep = RepresentationOf(store_rep.machine_type()); |
311 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { | 311 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { |
312 DCHECK(rep == kRepTagged); | 312 DCHECK(rep == kRepTagged); |
313 // TODO(dcarney): refactor RecordWrite function to take temp registers | 313 // TODO(dcarney): refactor RecordWrite function to take temp registers |
314 // and pass them here instead of using fixed regs | 314 // and pass them here instead of using fixed regs |
315 // TODO(dcarney): handle immediate indices. | 315 // TODO(dcarney): handle immediate indices. |
316 InstructionOperand* temps[] = {g.TempRegister(x11), g.TempRegister(x12)}; | 316 InstructionOperand temps[] = {g.TempRegister(x11), g.TempRegister(x12)}; |
317 Emit(kArm64StoreWriteBarrier, NULL, g.UseFixed(base, x10), | 317 Emit(kArm64StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, x10), |
318 g.UseFixed(index, x11), g.UseFixed(value, x12), arraysize(temps), | 318 g.UseFixed(index, x11), g.UseFixed(value, x12), arraysize(temps), |
319 temps); | 319 temps); |
320 return; | 320 return; |
321 } | 321 } |
322 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); | 322 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); |
323 ArchOpcode opcode; | 323 ArchOpcode opcode; |
324 ImmediateMode immediate_mode = kNoImmediate; | 324 ImmediateMode immediate_mode = kNoImmediate; |
325 switch (rep) { | 325 switch (rep) { |
326 case kRepFloat32: | 326 case kRepFloat32: |
327 opcode = kArm64StrS; | 327 opcode = kArm64StrS; |
(...skipping 19 matching lines...) Expand all Loading... |
347 case kRepTagged: // Fall through. | 347 case kRepTagged: // Fall through. |
348 case kRepWord64: | 348 case kRepWord64: |
349 opcode = kArm64Str; | 349 opcode = kArm64Str; |
350 immediate_mode = kLoadStoreImm64; | 350 immediate_mode = kLoadStoreImm64; |
351 break; | 351 break; |
352 default: | 352 default: |
353 UNREACHABLE(); | 353 UNREACHABLE(); |
354 return; | 354 return; |
355 } | 355 } |
356 if (g.CanBeImmediate(index, immediate_mode)) { | 356 if (g.CanBeImmediate(index, immediate_mode)) { |
357 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, | 357 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
358 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 358 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); |
359 } else { | 359 } else { |
360 Emit(opcode | AddressingModeField::encode(kMode_MRR), NULL, | 360 Emit(opcode | AddressingModeField::encode(kMode_MRR), g.NoOutput(), |
361 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); | 361 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); |
362 } | 362 } |
363 } | 363 } |
364 | 364 |
365 | 365 |
366 void InstructionSelector::VisitCheckedLoad(Node* node) { | 366 void InstructionSelector::VisitCheckedLoad(Node* node) { |
367 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 367 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
368 MachineType typ = TypeOf(OpParameter<MachineType>(node)); | 368 MachineType typ = TypeOf(OpParameter<MachineType>(node)); |
369 Arm64OperandGenerator g(this); | 369 Arm64OperandGenerator g(this); |
370 Node* const buffer = node->InputAt(0); | 370 Node* const buffer = node->InputAt(0); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 case kRepFloat32: | 417 case kRepFloat32: |
418 opcode = kCheckedStoreFloat32; | 418 opcode = kCheckedStoreFloat32; |
419 break; | 419 break; |
420 case kRepFloat64: | 420 case kRepFloat64: |
421 opcode = kCheckedStoreFloat64; | 421 opcode = kCheckedStoreFloat64; |
422 break; | 422 break; |
423 default: | 423 default: |
424 UNREACHABLE(); | 424 UNREACHABLE(); |
425 return; | 425 return; |
426 } | 426 } |
427 Emit(opcode, nullptr, g.UseRegister(buffer), g.UseRegister(offset), | 427 Emit(opcode, g.NoOutput(), g.UseRegister(buffer), g.UseRegister(offset), |
428 g.UseOperand(length, kArithmeticImm), g.UseRegister(value)); | 428 g.UseOperand(length, kArithmeticImm), g.UseRegister(value)); |
429 } | 429 } |
430 | 430 |
431 | 431 |
432 template <typename Matcher> | 432 template <typename Matcher> |
433 static void VisitLogical(InstructionSelector* selector, Node* node, Matcher* m, | 433 static void VisitLogical(InstructionSelector* selector, Node* node, Matcher* m, |
434 ArchOpcode opcode, bool left_can_cover, | 434 ArchOpcode opcode, bool left_can_cover, |
435 bool right_can_cover, ImmediateMode imm_mode) { | 435 bool right_can_cover, ImmediateMode imm_mode) { |
436 Arm64OperandGenerator g(selector); | 436 Arm64OperandGenerator g(selector); |
437 | 437 |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 } | 857 } |
858 } | 858 } |
859 | 859 |
860 VisitRRR(this, kArm64Mul, node); | 860 VisitRRR(this, kArm64Mul, node); |
861 } | 861 } |
862 | 862 |
863 | 863 |
864 void InstructionSelector::VisitInt32MulHigh(Node* node) { | 864 void InstructionSelector::VisitInt32MulHigh(Node* node) { |
865 // TODO(arm64): Can we do better here? | 865 // TODO(arm64): Can we do better here? |
866 Arm64OperandGenerator g(this); | 866 Arm64OperandGenerator g(this); |
867 InstructionOperand* const smull_operand = g.TempRegister(); | 867 InstructionOperand const smull_operand = g.TempRegister(); |
868 Emit(kArm64Smull, smull_operand, g.UseRegister(node->InputAt(0)), | 868 Emit(kArm64Smull, smull_operand, g.UseRegister(node->InputAt(0)), |
869 g.UseRegister(node->InputAt(1))); | 869 g.UseRegister(node->InputAt(1))); |
870 Emit(kArm64Asr, g.DefineAsRegister(node), smull_operand, g.TempImmediate(32)); | 870 Emit(kArm64Asr, g.DefineAsRegister(node), smull_operand, g.TempImmediate(32)); |
871 } | 871 } |
872 | 872 |
873 | 873 |
874 void InstructionSelector::VisitUint32MulHigh(Node* node) { | 874 void InstructionSelector::VisitUint32MulHigh(Node* node) { |
875 // TODO(arm64): Can we do better here? | 875 // TODO(arm64): Can we do better here? |
876 Arm64OperandGenerator g(this); | 876 Arm64OperandGenerator g(this); |
877 InstructionOperand* const smull_operand = g.TempRegister(); | 877 InstructionOperand const smull_operand = g.TempRegister(); |
878 Emit(kArm64Umull, smull_operand, g.UseRegister(node->InputAt(0)), | 878 Emit(kArm64Umull, smull_operand, g.UseRegister(node->InputAt(0)), |
879 g.UseRegister(node->InputAt(1))); | 879 g.UseRegister(node->InputAt(1))); |
880 Emit(kArm64Lsr, g.DefineAsRegister(node), smull_operand, g.TempImmediate(32)); | 880 Emit(kArm64Lsr, g.DefineAsRegister(node), smull_operand, g.TempImmediate(32)); |
881 } | 881 } |
882 | 882 |
883 | 883 |
884 void InstructionSelector::VisitInt32Div(Node* node) { | 884 void InstructionSelector::VisitInt32Div(Node* node) { |
885 VisitRRR(this, kArm64Idiv32, node); | 885 VisitRRR(this, kArm64Idiv32, node); |
886 } | 886 } |
887 | 887 |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1100 | 1100 |
1101 // Push the arguments to the stack. | 1101 // Push the arguments to the stack. |
1102 bool pushed_count_uneven = buffer.pushed_nodes.size() & 1; | 1102 bool pushed_count_uneven = buffer.pushed_nodes.size() & 1; |
1103 int aligned_push_count = buffer.pushed_nodes.size(); | 1103 int aligned_push_count = buffer.pushed_nodes.size(); |
1104 // TODO(dcarney): claim and poke probably take small immediates, | 1104 // TODO(dcarney): claim and poke probably take small immediates, |
1105 // loop here or whatever. | 1105 // loop here or whatever. |
1106 // Bump the stack pointer(s). | 1106 // Bump the stack pointer(s). |
1107 if (aligned_push_count > 0) { | 1107 if (aligned_push_count > 0) { |
1108 // TODO(dcarney): it would be better to bump the csp here only | 1108 // TODO(dcarney): it would be better to bump the csp here only |
1109 // and emit paired stores with increment for non c frames. | 1109 // and emit paired stores with increment for non c frames. |
1110 Emit(kArm64Claim | MiscField::encode(aligned_push_count), NULL); | 1110 Emit(kArm64Claim | MiscField::encode(aligned_push_count), g.NoOutput()); |
1111 } | 1111 } |
1112 // Move arguments to the stack. | 1112 // Move arguments to the stack. |
1113 { | 1113 { |
1114 int slot = buffer.pushed_nodes.size() - 1; | 1114 int slot = buffer.pushed_nodes.size() - 1; |
1115 // Emit the uneven pushes. | 1115 // Emit the uneven pushes. |
1116 if (pushed_count_uneven) { | 1116 if (pushed_count_uneven) { |
1117 Node* input = buffer.pushed_nodes[slot]; | 1117 Node* input = buffer.pushed_nodes[slot]; |
1118 Emit(kArm64Poke | MiscField::encode(slot), NULL, g.UseRegister(input)); | 1118 Emit(kArm64Poke | MiscField::encode(slot), g.NoOutput(), |
| 1119 g.UseRegister(input)); |
1119 slot--; | 1120 slot--; |
1120 } | 1121 } |
1121 // Now all pushes can be done in pairs. | 1122 // Now all pushes can be done in pairs. |
1122 for (; slot >= 0; slot -= 2) { | 1123 for (; slot >= 0; slot -= 2) { |
1123 Emit(kArm64PokePair | MiscField::encode(slot), NULL, | 1124 Emit(kArm64PokePair | MiscField::encode(slot), g.NoOutput(), |
1124 g.UseRegister(buffer.pushed_nodes[slot]), | 1125 g.UseRegister(buffer.pushed_nodes[slot]), |
1125 g.UseRegister(buffer.pushed_nodes[slot - 1])); | 1126 g.UseRegister(buffer.pushed_nodes[slot - 1])); |
1126 } | 1127 } |
1127 } | 1128 } |
1128 | 1129 |
1129 // Select the appropriate opcode based on the call type. | 1130 // Select the appropriate opcode based on the call type. |
1130 InstructionCode opcode; | 1131 InstructionCode opcode; |
1131 switch (descriptor->kind()) { | 1132 switch (descriptor->kind()) { |
1132 case CallDescriptor::kCallCodeObject: { | 1133 case CallDescriptor::kCallCodeObject: { |
1133 opcode = kArchCallCodeObject; | 1134 opcode = kArchCallCodeObject; |
1134 break; | 1135 break; |
1135 } | 1136 } |
1136 case CallDescriptor::kCallJSFunction: | 1137 case CallDescriptor::kCallJSFunction: |
1137 opcode = kArchCallJSFunction; | 1138 opcode = kArchCallJSFunction; |
1138 break; | 1139 break; |
1139 default: | 1140 default: |
1140 UNREACHABLE(); | 1141 UNREACHABLE(); |
1141 return; | 1142 return; |
1142 } | 1143 } |
1143 opcode |= MiscField::encode(descriptor->flags()); | 1144 opcode |= MiscField::encode(descriptor->flags()); |
1144 | 1145 |
1145 // Emit the call instruction. | 1146 // Emit the call instruction. |
1146 InstructionOperand** first_output = | 1147 InstructionOperand* first_output = |
1147 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; | 1148 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; |
1148 Instruction* call_instr = | 1149 Instruction* call_instr = |
1149 Emit(opcode, buffer.outputs.size(), first_output, | 1150 Emit(opcode, buffer.outputs.size(), first_output, |
1150 buffer.instruction_args.size(), &buffer.instruction_args.front()); | 1151 buffer.instruction_args.size(), &buffer.instruction_args.front()); |
1151 call_instr->MarkAsCall(); | 1152 call_instr->MarkAsCall(); |
1152 } | 1153 } |
1153 | 1154 |
1154 | 1155 |
1155 // Shared routine for multiple compare operations. | 1156 // Shared routine for multiple compare operations. |
1156 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1157 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1157 InstructionOperand* left, InstructionOperand* right, | 1158 InstructionOperand left, InstructionOperand right, |
1158 FlagsContinuation* cont) { | 1159 FlagsContinuation* cont) { |
1159 Arm64OperandGenerator g(selector); | 1160 Arm64OperandGenerator g(selector); |
1160 opcode = cont->Encode(opcode); | 1161 opcode = cont->Encode(opcode); |
1161 if (cont->IsBranch()) { | 1162 if (cont->IsBranch()) { |
1162 selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()), | 1163 selector->Emit(opcode, g.NoOutput(), left, right, |
| 1164 g.Label(cont->true_block()), |
1163 g.Label(cont->false_block()))->MarkAsControl(); | 1165 g.Label(cont->false_block()))->MarkAsControl(); |
1164 } else { | 1166 } else { |
1165 DCHECK(cont->IsSet()); | 1167 DCHECK(cont->IsSet()); |
1166 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 1168 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
1167 } | 1169 } |
1168 } | 1170 } |
1169 | 1171 |
1170 | 1172 |
1171 // Shared routine for multiple word compare operations. | 1173 // Shared routine for multiple word compare operations. |
1172 static void VisitWordCompare(InstructionSelector* selector, Node* node, | 1174 static void VisitWordCompare(InstructionSelector* selector, Node* node, |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1341 case IrOpcode::kInt32Sub: | 1343 case IrOpcode::kInt32Sub: |
1342 return VisitWordCompare(this, value, kArm64Cmp32, &cont, false, | 1344 return VisitWordCompare(this, value, kArm64Cmp32, &cont, false, |
1343 kArithmeticImm); | 1345 kArithmeticImm); |
1344 case IrOpcode::kWord32And: { | 1346 case IrOpcode::kWord32And: { |
1345 Int32BinopMatcher m(value); | 1347 Int32BinopMatcher m(value); |
1346 if (m.right().HasValue() && | 1348 if (m.right().HasValue() && |
1347 (base::bits::CountPopulation32(m.right().Value()) == 1)) { | 1349 (base::bits::CountPopulation32(m.right().Value()) == 1)) { |
1348 // If the mask has only one bit set, we can use tbz/tbnz. | 1350 // If the mask has only one bit set, we can use tbz/tbnz. |
1349 DCHECK((cont.condition() == kEqual) || | 1351 DCHECK((cont.condition() == kEqual) || |
1350 (cont.condition() == kNotEqual)); | 1352 (cont.condition() == kNotEqual)); |
1351 Emit(cont.Encode(kArm64TestAndBranch32), NULL, | 1353 Emit(cont.Encode(kArm64TestAndBranch32), g.NoOutput(), |
1352 g.UseRegister(m.left().node()), | 1354 g.UseRegister(m.left().node()), |
1353 g.TempImmediate( | 1355 g.TempImmediate( |
1354 base::bits::CountTrailingZeros32(m.right().Value())), | 1356 base::bits::CountTrailingZeros32(m.right().Value())), |
1355 g.Label(cont.true_block()), | 1357 g.Label(cont.true_block()), |
1356 g.Label(cont.false_block()))->MarkAsControl(); | 1358 g.Label(cont.false_block()))->MarkAsControl(); |
1357 return; | 1359 return; |
1358 } | 1360 } |
1359 return VisitWordCompare(this, value, kArm64Tst32, &cont, true, | 1361 return VisitWordCompare(this, value, kArm64Tst32, &cont, true, |
1360 kLogical32Imm); | 1362 kLogical32Imm); |
1361 } | 1363 } |
1362 case IrOpcode::kWord64And: { | 1364 case IrOpcode::kWord64And: { |
1363 Int64BinopMatcher m(value); | 1365 Int64BinopMatcher m(value); |
1364 if (m.right().HasValue() && | 1366 if (m.right().HasValue() && |
1365 (base::bits::CountPopulation64(m.right().Value()) == 1)) { | 1367 (base::bits::CountPopulation64(m.right().Value()) == 1)) { |
1366 // If the mask has only one bit set, we can use tbz/tbnz. | 1368 // If the mask has only one bit set, we can use tbz/tbnz. |
1367 DCHECK((cont.condition() == kEqual) || | 1369 DCHECK((cont.condition() == kEqual) || |
1368 (cont.condition() == kNotEqual)); | 1370 (cont.condition() == kNotEqual)); |
1369 Emit(cont.Encode(kArm64TestAndBranch), NULL, | 1371 Emit(cont.Encode(kArm64TestAndBranch), g.NoOutput(), |
1370 g.UseRegister(m.left().node()), | 1372 g.UseRegister(m.left().node()), |
1371 g.TempImmediate( | 1373 g.TempImmediate( |
1372 base::bits::CountTrailingZeros64(m.right().Value())), | 1374 base::bits::CountTrailingZeros64(m.right().Value())), |
1373 g.Label(cont.true_block()), | 1375 g.Label(cont.true_block()), |
1374 g.Label(cont.false_block()))->MarkAsControl(); | 1376 g.Label(cont.false_block()))->MarkAsControl(); |
1375 return; | 1377 return; |
1376 } | 1378 } |
1377 return VisitWordCompare(this, value, kArm64Tst, &cont, true, | 1379 return VisitWordCompare(this, value, kArm64Tst, &cont, true, |
1378 kLogical64Imm); | 1380 kLogical64Imm); |
1379 } | 1381 } |
1380 default: | 1382 default: |
1381 break; | 1383 break; |
1382 } | 1384 } |
1383 } | 1385 } |
1384 | 1386 |
1385 // Branch could not be combined with a compare, compare against 0 and branch. | 1387 // Branch could not be combined with a compare, compare against 0 and branch. |
1386 Emit(cont.Encode(kArm64CompareAndBranch32), NULL, g.UseRegister(value), | 1388 Emit(cont.Encode(kArm64CompareAndBranch32), g.NoOutput(), |
1387 g.Label(cont.true_block()), | 1389 g.UseRegister(value), g.Label(cont.true_block()), |
1388 g.Label(cont.false_block()))->MarkAsControl(); | 1390 g.Label(cont.false_block()))->MarkAsControl(); |
1389 } | 1391 } |
1390 | 1392 |
1391 | 1393 |
1392 void InstructionSelector::VisitWord32Equal(Node* const node) { | 1394 void InstructionSelector::VisitWord32Equal(Node* const node) { |
1393 Node* const user = node; | 1395 Node* const user = node; |
1394 FlagsContinuation cont(kEqual, node); | 1396 FlagsContinuation cont(kEqual, node); |
1395 Int32BinopMatcher m(user); | 1397 Int32BinopMatcher m(user); |
1396 if (m.right().Is(0)) { | 1398 if (m.right().Is(0)) { |
1397 Node* const value = m.left().node(); | 1399 Node* const value = m.left().node(); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1527 MachineOperatorBuilder::kFloat64RoundTruncate | | 1529 MachineOperatorBuilder::kFloat64RoundTruncate | |
1528 MachineOperatorBuilder::kFloat64RoundTiesAway | | 1530 MachineOperatorBuilder::kFloat64RoundTiesAway | |
1529 MachineOperatorBuilder::kWord32ShiftIsSafe | | 1531 MachineOperatorBuilder::kWord32ShiftIsSafe | |
1530 MachineOperatorBuilder::kInt32DivIsSafe | | 1532 MachineOperatorBuilder::kInt32DivIsSafe | |
1531 MachineOperatorBuilder::kUint32DivIsSafe; | 1533 MachineOperatorBuilder::kUint32DivIsSafe; |
1532 } | 1534 } |
1533 | 1535 |
1534 } // namespace compiler | 1536 } // namespace compiler |
1535 } // namespace internal | 1537 } // namespace internal |
1536 } // namespace v8 | 1538 } // namespace v8 |
OLD | NEW |