ARMHazardRecognizer.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. //===-- ARMHazardRecognizer.cpp - ARM postra hazard recognizer ------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "ARMHazardRecognizer.h"
  10. #include "ARMBaseInstrInfo.h"
  11. #include "ARMBaseRegisterInfo.h"
  12. #include "ARMSubtarget.h"
  13. #include "llvm/CodeGen/MachineInstr.h"
  14. #include "llvm/CodeGen/ScheduleDAG.h"
  15. #include "llvm/Target/TargetRegisterInfo.h"
  16. using namespace llvm;
  17. static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI,
  18. const TargetRegisterInfo &TRI) {
  19. // FIXME: Detect integer instructions properly.
  20. const MCInstrDesc &MCID = MI->getDesc();
  21. unsigned Domain = MCID.TSFlags & ARMII::DomainMask;
  22. if (MI->mayStore())
  23. return false;
  24. unsigned Opcode = MCID.getOpcode();
  25. if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
  26. return false;
  27. if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON))
  28. return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI);
  29. return false;
  30. }
  31. ScheduleHazardRecognizer::HazardType
  32. ARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
  33. assert(Stalls == 0 && "ARM hazards don't support scoreboard lookahead");
  34. MachineInstr *MI = SU->getInstr();
  35. if (!MI->isDebugValue()) {
  36. // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following
  37. // a VMLA / VMLS will cause 4 cycle stall.
  38. const MCInstrDesc &MCID = MI->getDesc();
  39. if (LastMI && (MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) {
  40. MachineInstr *DefMI = LastMI;
  41. const MCInstrDesc &LastMCID = LastMI->getDesc();
  42. const TargetMachine &TM =
  43. MI->getParent()->getParent()->getTarget();
  44. const ARMBaseInstrInfo &TII =
  45. *static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
  46. // Skip over one non-VFP / NEON instruction.
  47. if (!LastMI->isBarrier() &&
  48. // On A9, AGU and NEON/FPU are muxed.
  49. !(TII.getSubtarget().isLikeA9() &&
  50. (LastMI->mayLoad() || LastMI->mayStore())) &&
  51. (LastMCID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) {
  52. MachineBasicBlock::iterator I = LastMI;
  53. if (I != LastMI->getParent()->begin()) {
  54. I = std::prev(I);
  55. DefMI = &*I;
  56. }
  57. }
  58. if (TII.isFpMLxInstruction(DefMI->getOpcode()) &&
  59. (TII.canCauseFpMLxStall(MI->getOpcode()) ||
  60. hasRAWHazard(DefMI, MI, TII.getRegisterInfo()))) {
  61. // Try to schedule another instruction for the next 4 cycles.
  62. if (FpMLxStalls == 0)
  63. FpMLxStalls = 4;
  64. return Hazard;
  65. }
  66. }
  67. }
  68. return ScoreboardHazardRecognizer::getHazardType(SU, Stalls);
  69. }
  70. void ARMHazardRecognizer::Reset() {
  71. LastMI = 0;
  72. FpMLxStalls = 0;
  73. ScoreboardHazardRecognizer::Reset();
  74. }
  75. void ARMHazardRecognizer::EmitInstruction(SUnit *SU) {
  76. MachineInstr *MI = SU->getInstr();
  77. if (!MI->isDebugValue()) {
  78. LastMI = MI;
  79. FpMLxStalls = 0;
  80. }
  81. ScoreboardHazardRecognizer::EmitInstruction(SU);
  82. }
  83. void ARMHazardRecognizer::AdvanceCycle() {
  84. if (FpMLxStalls && --FpMLxStalls == 0)
  85. // Stalled for 4 cycles but still can't schedule any other instructions.
  86. LastMI = 0;
  87. ScoreboardHazardRecognizer::AdvanceCycle();
  88. }
  89. void ARMHazardRecognizer::RecedeCycle() {
  90. llvm_unreachable("reverse ARM hazard checking unsupported");
  91. }