| 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 320 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 331     selector->Emit(kArmMls, result_operand, div_operand, right_operand, | 331     selector->Emit(kArmMls, result_operand, div_operand, right_operand, | 
| 332                    left_operand); | 332                    left_operand); | 
| 333   } else { | 333   } else { | 
| 334     InstructionOperand mul_operand = g.TempRegister(); | 334     InstructionOperand mul_operand = g.TempRegister(); | 
| 335     selector->Emit(kArmMul, mul_operand, div_operand, right_operand); | 335     selector->Emit(kArmMul, mul_operand, div_operand, right_operand); | 
| 336     selector->Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_R), | 336     selector->Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_R), | 
| 337                    result_operand, left_operand, mul_operand); | 337                    result_operand, left_operand, mul_operand); | 
| 338   } | 338   } | 
| 339 } | 339 } | 
| 340 | 340 | 
|  | 341 void EmitLoad(InstructionSelector* selector, InstructionCode opcode, | 
|  | 342               InstructionOperand* output, Node* base, Node* index) { | 
|  | 343   ArmOperandGenerator g(selector); | 
|  | 344   InstructionOperand inputs[3]; | 
|  | 345   size_t input_count = 2; | 
|  | 346 | 
|  | 347   inputs[0] = g.UseRegister(base); | 
|  | 348   if (g.CanBeImmediate(index, opcode)) { | 
|  | 349     inputs[1] = g.UseImmediate(index); | 
|  | 350     opcode |= AddressingModeField::encode(kMode_Offset_RI); | 
|  | 351   } else if ((opcode == kArmLdr) && | 
|  | 352              TryMatchLSLImmediate(selector, &opcode, index, &inputs[1], | 
|  | 353                                   &inputs[2])) { | 
|  | 354     input_count = 3; | 
|  | 355   } else { | 
|  | 356     inputs[1] = g.UseRegister(index); | 
|  | 357     opcode |= AddressingModeField::encode(kMode_Offset_RR); | 
|  | 358   } | 
|  | 359   selector->Emit(opcode, 1, output, input_count, inputs); | 
|  | 360 } | 
|  | 361 | 
|  | 362 void EmitStore(InstructionSelector* selector, InstructionCode opcode, | 
|  | 363                size_t input_count, InstructionOperand* inputs, | 
|  | 364                Node* index) { | 
|  | 365   ArmOperandGenerator g(selector); | 
|  | 366 | 
|  | 367   if (g.CanBeImmediate(index, opcode)) { | 
|  | 368     inputs[input_count++] = g.UseImmediate(index); | 
|  | 369     opcode |= AddressingModeField::encode(kMode_Offset_RI); | 
|  | 370   } else if ((opcode == kArmStr) && | 
|  | 371              TryMatchLSLImmediate(selector, &opcode, index, &inputs[2], | 
|  | 372                                   &inputs[3])) { | 
|  | 373     input_count = 4; | 
|  | 374   } else { | 
|  | 375     inputs[input_count++] = g.UseRegister(index); | 
|  | 376     opcode |= AddressingModeField::encode(kMode_Offset_RR); | 
|  | 377   } | 
|  | 378   selector->Emit(opcode, 0, nullptr, input_count, inputs); | 
|  | 379 } | 
|  | 380 | 
| 341 }  // namespace | 381 }  // namespace | 
| 342 | 382 | 
| 343 | 383 | 
| 344 void InstructionSelector::VisitLoad(Node* node) { | 384 void InstructionSelector::VisitLoad(Node* node) { | 
| 345   LoadRepresentation load_rep = LoadRepresentationOf(node->op()); | 385   LoadRepresentation load_rep = LoadRepresentationOf(node->op()); | 
| 346   ArmOperandGenerator g(this); | 386   ArmOperandGenerator g(this); | 
| 347   Node* base = node->InputAt(0); | 387   Node* base = node->InputAt(0); | 
| 348   Node* index = node->InputAt(1); | 388   Node* index = node->InputAt(1); | 
| 349   InstructionOperand inputs[3]; |  | 
| 350   size_t input_count = 0; |  | 
| 351   InstructionOperand outputs[1]; |  | 
| 352 | 389 | 
| 353   InstructionCode opcode = kArchNop; | 390   InstructionCode opcode = kArchNop; | 
| 354   switch (load_rep.representation()) { | 391   switch (load_rep.representation()) { | 
| 355     case MachineRepresentation::kFloat32: | 392     case MachineRepresentation::kFloat32: | 
| 356       opcode = kArmVldrF32; | 393       opcode = kArmVldrF32; | 
| 357       break; | 394       break; | 
| 358     case MachineRepresentation::kFloat64: | 395     case MachineRepresentation::kFloat64: | 
| 359       opcode = kArmVldrF64; | 396       opcode = kArmVldrF64; | 
| 360       break; | 397       break; | 
| 361     case MachineRepresentation::kBit:  // Fall through. | 398     case MachineRepresentation::kBit:  // Fall through. | 
| 362     case MachineRepresentation::kWord8: | 399     case MachineRepresentation::kWord8: | 
| 363       opcode = load_rep.IsUnsigned() ? kArmLdrb : kArmLdrsb; | 400       opcode = load_rep.IsUnsigned() ? kArmLdrb : kArmLdrsb; | 
| 364       break; | 401       break; | 
| 365     case MachineRepresentation::kWord16: | 402     case MachineRepresentation::kWord16: | 
| 366       opcode = load_rep.IsUnsigned() ? kArmLdrh : kArmLdrsh; | 403       opcode = load_rep.IsUnsigned() ? kArmLdrh : kArmLdrsh; | 
| 367       break; | 404       break; | 
| 368     case MachineRepresentation::kTagged:  // Fall through. | 405     case MachineRepresentation::kTagged:  // Fall through. | 
| 369     case MachineRepresentation::kWord32: | 406     case MachineRepresentation::kWord32: | 
| 370       opcode = kArmLdr; | 407       opcode = kArmLdr; | 
| 371       break; | 408       break; | 
| 372     case MachineRepresentation::kWord64:   // Fall through. | 409     case MachineRepresentation::kWord64:   // Fall through. | 
| 373     case MachineRepresentation::kSimd128:  // Fall through. | 410     case MachineRepresentation::kSimd128:  // Fall through. | 
| 374     case MachineRepresentation::kNone: | 411     case MachineRepresentation::kNone: | 
| 375       UNREACHABLE(); | 412       UNREACHABLE(); | 
| 376       return; | 413       return; | 
| 377   } | 414   } | 
| 378 | 415 | 
| 379   outputs[0] = g.DefineAsRegister(node); | 416   InstructionOperand output = g.DefineAsRegister(node); | 
| 380   inputs[0] = g.UseRegister(base); | 417   EmitLoad(this, opcode, &output, base, index); | 
| 381 |  | 
| 382   if (g.CanBeImmediate(index, opcode)) { |  | 
| 383     input_count = 2; |  | 
| 384     inputs[1] = g.UseImmediate(index); |  | 
| 385     opcode |= AddressingModeField::encode(kMode_Offset_RI); |  | 
| 386   } else if ((opcode == kArmLdr) && |  | 
| 387              TryMatchLSLImmediate(this, &opcode, index, &inputs[1], |  | 
| 388                                   &inputs[2])) { |  | 
| 389     input_count = 3; |  | 
| 390   } else { |  | 
| 391     input_count = 2; |  | 
| 392     inputs[1] = g.UseRegister(index); |  | 
| 393     opcode |= AddressingModeField::encode(kMode_Offset_RR); |  | 
| 394   } |  | 
| 395 |  | 
| 396   Emit(opcode, arraysize(outputs), outputs, input_count, inputs); |  | 
| 397 } | 418 } | 
| 398 | 419 | 
| 399 | 420 | 
| 400 void InstructionSelector::VisitStore(Node* node) { | 421 void InstructionSelector::VisitStore(Node* node) { | 
| 401   ArmOperandGenerator g(this); | 422   ArmOperandGenerator g(this); | 
| 402   Node* base = node->InputAt(0); | 423   Node* base = node->InputAt(0); | 
| 403   Node* index = node->InputAt(1); | 424   Node* index = node->InputAt(1); | 
| 404   Node* value = node->InputAt(2); | 425   Node* value = node->InputAt(2); | 
| 405 | 426 | 
| 406   StoreRepresentation store_rep = StoreRepresentationOf(node->op()); | 427   StoreRepresentation store_rep = StoreRepresentationOf(node->op()); | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 438         record_write_mode = RecordWriteMode::kValueIsAny; | 459         record_write_mode = RecordWriteMode::kValueIsAny; | 
| 439         break; | 460         break; | 
| 440     } | 461     } | 
| 441     InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; | 462     InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; | 
| 442     size_t const temp_count = arraysize(temps); | 463     size_t const temp_count = arraysize(temps); | 
| 443     InstructionCode code = kArchStoreWithWriteBarrier; | 464     InstructionCode code = kArchStoreWithWriteBarrier; | 
| 444     code |= AddressingModeField::encode(addressing_mode); | 465     code |= AddressingModeField::encode(addressing_mode); | 
| 445     code |= MiscField::encode(static_cast<int>(record_write_mode)); | 466     code |= MiscField::encode(static_cast<int>(record_write_mode)); | 
| 446     Emit(code, 0, nullptr, input_count, inputs, temp_count, temps); | 467     Emit(code, 0, nullptr, input_count, inputs, temp_count, temps); | 
| 447   } else { | 468   } else { | 
| 448     InstructionOperand inputs[4]; |  | 
| 449     size_t input_count = 0; |  | 
| 450 |  | 
| 451     InstructionCode opcode = kArchNop; | 469     InstructionCode opcode = kArchNop; | 
| 452     switch (rep) { | 470     switch (rep) { | 
| 453       case MachineRepresentation::kFloat32: | 471       case MachineRepresentation::kFloat32: | 
| 454         opcode = kArmVstrF32; | 472         opcode = kArmVstrF32; | 
| 455         break; | 473         break; | 
| 456       case MachineRepresentation::kFloat64: | 474       case MachineRepresentation::kFloat64: | 
| 457         opcode = kArmVstrF64; | 475         opcode = kArmVstrF64; | 
| 458         break; | 476         break; | 
| 459       case MachineRepresentation::kBit:  // Fall through. | 477       case MachineRepresentation::kBit:  // Fall through. | 
| 460       case MachineRepresentation::kWord8: | 478       case MachineRepresentation::kWord8: | 
| 461         opcode = kArmStrb; | 479         opcode = kArmStrb; | 
| 462         break; | 480         break; | 
| 463       case MachineRepresentation::kWord16: | 481       case MachineRepresentation::kWord16: | 
| 464         opcode = kArmStrh; | 482         opcode = kArmStrh; | 
| 465         break; | 483         break; | 
| 466       case MachineRepresentation::kTagged:  // Fall through. | 484       case MachineRepresentation::kTagged:  // Fall through. | 
| 467       case MachineRepresentation::kWord32: | 485       case MachineRepresentation::kWord32: | 
| 468         opcode = kArmStr; | 486         opcode = kArmStr; | 
| 469         break; | 487         break; | 
| 470       case MachineRepresentation::kWord64:   // Fall through. | 488       case MachineRepresentation::kWord64:   // Fall through. | 
| 471       case MachineRepresentation::kSimd128:  // Fall through. | 489       case MachineRepresentation::kSimd128:  // Fall through. | 
| 472       case MachineRepresentation::kNone: | 490       case MachineRepresentation::kNone: | 
| 473         UNREACHABLE(); | 491         UNREACHABLE(); | 
| 474         return; | 492         return; | 
| 475     } | 493     } | 
| 476 | 494 | 
| 477     inputs[0] = g.UseRegister(value); | 495     InstructionOperand inputs[4]; | 
| 478     inputs[1] = g.UseRegister(base); | 496     size_t input_count = 0; | 
| 479 | 497     inputs[input_count++] = g.UseRegister(value); | 
| 480     if (g.CanBeImmediate(index, opcode)) { | 498     inputs[input_count++] = g.UseRegister(base); | 
| 481       input_count = 3; | 499     EmitStore(this, opcode, input_count, inputs, index); | 
| 482       inputs[2] = g.UseImmediate(index); |  | 
| 483       opcode |= AddressingModeField::encode(kMode_Offset_RI); |  | 
| 484     } else if ((opcode == kArmStr) && |  | 
| 485                TryMatchLSLImmediate(this, &opcode, index, &inputs[2], |  | 
| 486                                     &inputs[3])) { |  | 
| 487       input_count = 4; |  | 
| 488     } else { |  | 
| 489       input_count = 3; |  | 
| 490       inputs[2] = g.UseRegister(index); |  | 
| 491       opcode |= AddressingModeField::encode(kMode_Offset_RR); |  | 
| 492     } |  | 
| 493     Emit(opcode, 0, nullptr, input_count, inputs); |  | 
| 494   } | 500   } | 
| 495 } | 501 } | 
| 496 | 502 | 
| 497 // Architecture supports unaligned access, therefore VisitLoad is used instead | 503 void InstructionSelector::VisitUnalignedLoad(Node* node) { | 
| 498 void InstructionSelector::VisitUnalignedLoad(Node* node) { UNREACHABLE(); } | 504   UnalignedLoadRepresentation load_rep = | 
|  | 505       UnalignedLoadRepresentationOf(node->op()); | 
|  | 506   ArmOperandGenerator g(this); | 
|  | 507   Node* base = node->InputAt(0); | 
|  | 508   Node* index = node->InputAt(1); | 
| 499 | 509 | 
| 500 // Architecture supports unaligned access, therefore VisitStore is used instead | 510   InstructionCode opcode = kArmLdr; | 
| 501 void InstructionSelector::VisitUnalignedStore(Node* node) { UNREACHABLE(); } | 511   // Only floating point loads need to be specially handled; integer loads | 
|  | 512   // support unaligned access. We support unaligned FP loads by loading to | 
|  | 513   // integer registers first, then moving to the destination FP register. | 
|  | 514   switch (load_rep.representation()) { | 
|  | 515     case MachineRepresentation::kFloat32: { | 
|  | 516       InstructionOperand temp = g.TempRegister(); | 
|  | 517       EmitLoad(this, opcode, &temp, base, index); | 
|  | 518       Emit(kArmVmovF32U32, g.DefineAsRegister(node), temp); | 
|  | 519       return; | 
|  | 520     } | 
|  | 521     case MachineRepresentation::kFloat64: { | 
|  | 522       // TODO(arm): use vld1.8 for this when NEON is available. | 
|  | 523       // Compute the address of the least-significant half of the FP value. | 
|  | 524       // We assume that the base node is unlikely to be an encodable immediate | 
|  | 525       // or the result of a shift operation, so only consider the addressing | 
|  | 526       // mode that should be used for the index node. | 
|  | 527       InstructionCode add_opcode = kArmAdd; | 
|  | 528       InstructionOperand inputs[3]; | 
|  | 529       inputs[0] = g.UseRegister(base); | 
|  | 530 | 
|  | 531       size_t input_count; | 
|  | 532       if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count, | 
|  | 533                                    &inputs[1])) { | 
|  | 534         // input_count has been set by TryMatchImmediateOrShift(), so increment | 
|  | 535         // it to account for the base register in inputs[0]. | 
|  | 536         input_count++; | 
|  | 537       } else { | 
|  | 538         add_opcode |= AddressingModeField::encode(kMode_Operand2_R); | 
|  | 539         inputs[1] = g.UseRegister(index); | 
|  | 540         input_count = 2;  // Base register and index. | 
|  | 541       } | 
|  | 542 | 
|  | 543       InstructionOperand addr = g.TempRegister(); | 
|  | 544       Emit(add_opcode, 1, &addr, input_count, inputs); | 
|  | 545 | 
|  | 546       // Load both halves and move to an FP register. | 
|  | 547       InstructionOperand fp_lo = g.TempRegister(); | 
|  | 548       InstructionOperand fp_hi = g.TempRegister(); | 
|  | 549       opcode |= AddressingModeField::encode(kMode_Offset_RI); | 
|  | 550       Emit(opcode, fp_lo, addr, g.TempImmediate(0)); | 
|  | 551       Emit(opcode, fp_hi, addr, g.TempImmediate(4)); | 
|  | 552       Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), fp_lo, fp_hi); | 
|  | 553       return; | 
|  | 554     } | 
|  | 555     default: | 
|  | 556       // All other cases should support unaligned accesses. | 
|  | 557       UNREACHABLE(); | 
|  | 558       return; | 
|  | 559   } | 
|  | 560 } | 
|  | 561 | 
|  | 562 void InstructionSelector::VisitUnalignedStore(Node* node) { | 
|  | 563   ArmOperandGenerator g(this); | 
|  | 564   Node* base = node->InputAt(0); | 
|  | 565   Node* index = node->InputAt(1); | 
|  | 566   Node* value = node->InputAt(2); | 
|  | 567 | 
|  | 568   InstructionOperand inputs[4]; | 
|  | 569   size_t input_count = 0; | 
|  | 570 | 
|  | 571   UnalignedStoreRepresentation store_rep = | 
|  | 572       UnalignedStoreRepresentationOf(node->op()); | 
|  | 573 | 
|  | 574   // Only floating point stores need to be specially handled; integer stores | 
|  | 575   // support unaligned access. We support unaligned FP stores by moving the | 
|  | 576   // value to integer registers first, then storing to the destination address. | 
|  | 577   switch (store_rep) { | 
|  | 578     case MachineRepresentation::kFloat32: { | 
|  | 579       inputs[input_count++] = g.TempRegister(); | 
|  | 580       Emit(kArmVmovU32F32, inputs[0], g.UseRegister(value)); | 
|  | 581       inputs[input_count++] = g.UseRegister(base); | 
|  | 582       EmitStore(this, kArmStr, input_count, inputs, index); | 
|  | 583       return; | 
|  | 584     } | 
|  | 585     case MachineRepresentation::kFloat64: { | 
|  | 586       // TODO(arm): use vst1.8 for this when NEON is available. | 
|  | 587       // Store a 64-bit floating point value using two 32-bit integer stores. | 
|  | 588       // Computing the store address here would require three live temporary | 
|  | 589       // registers (fp<63:32>, fp<31:0>, address), so compute base + 4 after | 
|  | 590       // storing the least-significant half of the value. | 
|  | 591 | 
|  | 592       // First, move the 64-bit FP value into two temporary integer registers. | 
|  | 593       InstructionOperand fp[] = {g.TempRegister(), g.TempRegister()}; | 
|  | 594       inputs[input_count++] = g.UseRegister(value); | 
|  | 595       Emit(kArmVmovU32U32F64, arraysize(fp), fp, input_count, | 
|  | 596            inputs); | 
|  | 597 | 
|  | 598       // Store the least-significant half. | 
|  | 599       inputs[0] = fp[0];  // Low 32-bits of FP value. | 
|  | 600       inputs[input_count++] = g.UseRegister(base);  // First store base address. | 
|  | 601       EmitStore(this, kArmStr, input_count, inputs, index); | 
|  | 602 | 
|  | 603       // Store the most-significant half. | 
|  | 604       InstructionOperand base4 = g.TempRegister(); | 
|  | 605       Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_I), base4, | 
|  | 606            g.UseRegister(base), g.TempImmediate(4));  // Compute base + 4. | 
|  | 607       inputs[0] = fp[1];  // High 32-bits of FP value. | 
|  | 608       inputs[1] = base4;  // Second store base + 4 address. | 
|  | 609       EmitStore(this, kArmStr, input_count, inputs, index); | 
|  | 610       return; | 
|  | 611     } | 
|  | 612     default: | 
|  | 613       // All other cases should support unaligned accesses. | 
|  | 614       UNREACHABLE(); | 
|  | 615       return; | 
|  | 616   } | 
|  | 617 } | 
| 502 | 618 | 
| 503 void InstructionSelector::VisitCheckedLoad(Node* node) { | 619 void InstructionSelector::VisitCheckedLoad(Node* node) { | 
| 504   CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); | 620   CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); | 
| 505   ArmOperandGenerator g(this); | 621   ArmOperandGenerator g(this); | 
| 506   Node* const buffer = node->InputAt(0); | 622   Node* const buffer = node->InputAt(0); | 
| 507   Node* const offset = node->InputAt(1); | 623   Node* const offset = node->InputAt(1); | 
| 508   Node* const length = node->InputAt(2); | 624   Node* const length = node->InputAt(2); | 
| 509   ArchOpcode opcode = kArchNop; | 625   ArchOpcode opcode = kArchNop; | 
| 510   switch (load_rep.representation()) { | 626   switch (load_rep.representation()) { | 
| 511     case MachineRepresentation::kWord8: | 627     case MachineRepresentation::kWord8: | 
| (...skipping 1657 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2169              MachineOperatorBuilder::kFloat64RoundTiesEven | | 2285              MachineOperatorBuilder::kFloat64RoundTiesEven | | 
| 2170              MachineOperatorBuilder::kFloat32Neg | | 2286              MachineOperatorBuilder::kFloat32Neg | | 
| 2171              MachineOperatorBuilder::kFloat64Neg; | 2287              MachineOperatorBuilder::kFloat64Neg; | 
| 2172   } | 2288   } | 
| 2173   return flags; | 2289   return flags; | 
| 2174 } | 2290 } | 
| 2175 | 2291 | 
| 2176 // static | 2292 // static | 
| 2177 MachineOperatorBuilder::AlignmentRequirements | 2293 MachineOperatorBuilder::AlignmentRequirements | 
| 2178 InstructionSelector::AlignmentRequirements() { | 2294 InstructionSelector::AlignmentRequirements() { | 
|  | 2295   Vector<MachineType> req_aligned = Vector<MachineType>::New(2); | 
|  | 2296   req_aligned[0] = MachineType::Float32(); | 
|  | 2297   req_aligned[1] = MachineType::Float64(); | 
| 2179   return MachineOperatorBuilder::AlignmentRequirements:: | 2298   return MachineOperatorBuilder::AlignmentRequirements:: | 
| 2180       FullUnalignedAccessSupport(); | 2299       SomeUnalignedAccessUnsupported(req_aligned, req_aligned); | 
| 2181 } | 2300 } | 
| 2182 | 2301 | 
| 2183 }  // namespace compiler | 2302 }  // namespace compiler | 
| 2184 }  // namespace internal | 2303 }  // namespace internal | 
| 2185 }  // namespace v8 | 2304 }  // namespace v8 | 
| OLD | NEW | 
|---|