ARMHazardRecognizer.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. //===-- ARMHazardRecognizer.cpp - ARM postra hazard recognizer ------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "ARMHazardRecognizer.h"
  9. #include "ARMBaseInstrInfo.h"
  10. #include "ARMBaseRegisterInfo.h"
  11. #include "ARMSubtarget.h"
  12. #include "llvm/Analysis/ValueTracking.h"
  13. #include "llvm/CodeGen/MachineInstr.h"
  14. #include "llvm/CodeGen/ScheduleDAG.h"
  15. #include "llvm/CodeGen/TargetRegisterInfo.h"
  16. #include "llvm/Support/CommandLine.h"
  17. using namespace llvm;
  18. static cl::opt<int> DataBankMask("arm-data-bank-mask", cl::init(-1),
  19. cl::Hidden);
  20. static cl::opt<bool> AssumeITCMConflict("arm-assume-itcm-bankconflict",
  21. cl::init(false), cl::Hidden);
  22. static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI,
  23. const TargetRegisterInfo &TRI) {
  24. // FIXME: Detect integer instructions properly.
  25. const MCInstrDesc &MCID = MI->getDesc();
  26. unsigned Domain = MCID.TSFlags & ARMII::DomainMask;
  27. if (MI->mayStore())
  28. return false;
  29. unsigned Opcode = MCID.getOpcode();
  30. if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
  31. return false;
  32. if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON))
  33. return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI);
  34. return false;
  35. }
  36. ScheduleHazardRecognizer::HazardType
  37. ARMHazardRecognizerFPMLx::getHazardType(SUnit *SU, int Stalls) {
  38. assert(Stalls == 0 && "ARM hazards don't support scoreboard lookahead");
  39. MachineInstr *MI = SU->getInstr();
  40. if (!MI->isDebugInstr()) {
  41. // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following
  42. // a VMLA / VMLS will cause 4 cycle stall.
  43. const MCInstrDesc &MCID = MI->getDesc();
  44. if (LastMI && (MCID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) {
  45. MachineInstr *DefMI = LastMI;
  46. const MCInstrDesc &LastMCID = LastMI->getDesc();
  47. const MachineFunction *MF = MI->getParent()->getParent();
  48. const ARMBaseInstrInfo &TII = *static_cast<const ARMBaseInstrInfo *>(
  49. MF->getSubtarget().getInstrInfo());
  50. // Skip over one non-VFP / NEON instruction.
  51. if (!LastMI->isBarrier() &&
  52. !(TII.getSubtarget().hasMuxedUnits() && LastMI->mayLoadOrStore()) &&
  53. (LastMCID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) {
  54. MachineBasicBlock::iterator I = LastMI;
  55. if (I != LastMI->getParent()->begin()) {
  56. I = std::prev(I);
  57. DefMI = &*I;
  58. }
  59. }
  60. if (TII.isFpMLxInstruction(DefMI->getOpcode()) &&
  61. (TII.canCauseFpMLxStall(MI->getOpcode()) ||
  62. hasRAWHazard(DefMI, MI, TII.getRegisterInfo()))) {
  63. // Try to schedule another instruction for the next 4 cycles.
  64. if (FpMLxStalls == 0)
  65. FpMLxStalls = 4;
  66. return Hazard;
  67. }
  68. }
  69. }
  70. return NoHazard;
  71. }
  72. void ARMHazardRecognizerFPMLx::Reset() {
  73. LastMI = nullptr;
  74. FpMLxStalls = 0;
  75. }
  76. void ARMHazardRecognizerFPMLx::EmitInstruction(SUnit *SU) {
  77. MachineInstr *MI = SU->getInstr();
  78. if (!MI->isDebugInstr()) {
  79. LastMI = MI;
  80. FpMLxStalls = 0;
  81. }
  82. }
  83. void ARMHazardRecognizerFPMLx::AdvanceCycle() {
  84. if (FpMLxStalls && --FpMLxStalls == 0)
  85. // Stalled for 4 cycles but still can't schedule any other instructions.
  86. LastMI = nullptr;
  87. }
  88. void ARMHazardRecognizerFPMLx::RecedeCycle() {
  89. llvm_unreachable("reverse ARM hazard checking unsupported");
  90. }
  91. ///////// Bank conflicts handled as hazards //////////////
  92. static bool getBaseOffset(const MachineInstr &MI, const MachineOperand *&BaseOp,
  93. int64_t &Offset) {
  94. uint64_t TSFlags = MI.getDesc().TSFlags;
  95. unsigned AddrMode = (TSFlags & ARMII::AddrModeMask);
  96. unsigned IndexMode =
  97. (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
  98. // Address mode tells us what we want to know about operands for T2
  99. // instructions (but not size). It tells us size (but not about operands)
  100. // for T1 instructions.
  101. switch (AddrMode) {
  102. default:
  103. return false;
  104. case ARMII::AddrModeT2_i8:
  105. // t2LDRBT, t2LDRB_POST, t2LDRB_PRE, t2LDRBi8,
  106. // t2LDRHT, t2LDRH_POST, t2LDRH_PRE, t2LDRHi8,
  107. // t2LDRSBT, t2LDRSB_POST, t2LDRSB_PRE, t2LDRSBi8,
  108. // t2LDRSHT, t2LDRSH_POST, t2LDRSH_PRE, t2LDRSHi8,
  109. // t2LDRT, t2LDR_POST, t2LDR_PRE, t2LDRi8
  110. BaseOp = &MI.getOperand(1);
  111. Offset = (IndexMode == ARMII::IndexModePost)
  112. ? 0
  113. : (IndexMode == ARMII::IndexModePre ||
  114. IndexMode == ARMII::IndexModeUpd)
  115. ? MI.getOperand(3).getImm()
  116. : MI.getOperand(2).getImm();
  117. return true;
  118. case ARMII::AddrModeT2_i12:
  119. // t2LDRBi12, t2LDRHi12
  120. // t2LDRSBi12, t2LDRSHi12
  121. // t2LDRi12
  122. BaseOp = &MI.getOperand(1);
  123. Offset = MI.getOperand(2).getImm();
  124. return true;
  125. case ARMII::AddrModeT2_i8s4:
  126. // t2LDRD_POST, t2LDRD_PRE, t2LDRDi8
  127. BaseOp = &MI.getOperand(2);
  128. Offset = (IndexMode == ARMII::IndexModePost)
  129. ? 0
  130. : (IndexMode == ARMII::IndexModePre ||
  131. IndexMode == ARMII::IndexModeUpd)
  132. ? MI.getOperand(4).getImm()
  133. : MI.getOperand(3).getImm();
  134. return true;
  135. case ARMII::AddrModeT1_1:
  136. // tLDRBi, tLDRBr (watch out!), TLDRSB
  137. case ARMII::AddrModeT1_2:
  138. // tLDRHi, tLDRHr (watch out!), TLDRSH
  139. case ARMII::AddrModeT1_4:
  140. // tLDRi, tLDRr (watch out!)
  141. BaseOp = &MI.getOperand(1);
  142. Offset = MI.getOperand(2).isImm() ? MI.getOperand(2).getImm() : 0;
  143. return MI.getOperand(2).isImm();
  144. }
  145. return false;
  146. }
  147. ARMBankConflictHazardRecognizer::ARMBankConflictHazardRecognizer(
  148. const ScheduleDAG *DAG, int64_t CPUBankMask, bool CPUAssumeITCMConflict)
  149. : MF(DAG->MF), DL(DAG->MF.getDataLayout()),
  150. DataMask(DataBankMask.getNumOccurrences() ? int64_t(DataBankMask)
  151. : CPUBankMask),
  152. AssumeITCMBankConflict(AssumeITCMConflict.getNumOccurrences()
  153. ? AssumeITCMConflict
  154. : CPUAssumeITCMConflict) {
  155. MaxLookAhead = 1;
  156. }
  157. ScheduleHazardRecognizer::HazardType
  158. ARMBankConflictHazardRecognizer::CheckOffsets(unsigned O0, unsigned O1) {
  159. return (((O0 ^ O1) & DataMask) != 0) ? NoHazard : Hazard;
  160. }
  161. ScheduleHazardRecognizer::HazardType
  162. ARMBankConflictHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
  163. MachineInstr &L0 = *SU->getInstr();
  164. if (!L0.mayLoad() || L0.mayStore() || L0.getNumMemOperands() != 1)
  165. return NoHazard;
  166. auto MO0 = *L0.memoperands().begin();
  167. auto BaseVal0 = MO0->getValue();
  168. auto BasePseudoVal0 = MO0->getPseudoValue();
  169. int64_t Offset0 = 0;
  170. if (MO0->getSize() > 4)
  171. return NoHazard;
  172. bool SPvalid = false;
  173. const MachineOperand *SP = nullptr;
  174. int64_t SPOffset0 = 0;
  175. for (auto L1 : Accesses) {
  176. auto MO1 = *L1->memoperands().begin();
  177. auto BaseVal1 = MO1->getValue();
  178. auto BasePseudoVal1 = MO1->getPseudoValue();
  179. int64_t Offset1 = 0;
  180. // Pointers to the same object
  181. if (BaseVal0 && BaseVal1) {
  182. const Value *Ptr0, *Ptr1;
  183. Ptr0 = GetPointerBaseWithConstantOffset(BaseVal0, Offset0, DL, true);
  184. Ptr1 = GetPointerBaseWithConstantOffset(BaseVal1, Offset1, DL, true);
  185. if (Ptr0 == Ptr1 && Ptr0)
  186. return CheckOffsets(Offset0, Offset1);
  187. }
  188. if (BasePseudoVal0 && BasePseudoVal1 &&
  189. BasePseudoVal0->kind() == BasePseudoVal1->kind() &&
  190. BasePseudoVal0->kind() == PseudoSourceValue::FixedStack) {
  191. // Spills/fills
  192. auto FS0 = cast<FixedStackPseudoSourceValue>(BasePseudoVal0);
  193. auto FS1 = cast<FixedStackPseudoSourceValue>(BasePseudoVal1);
  194. Offset0 = MF.getFrameInfo().getObjectOffset(FS0->getFrameIndex());
  195. Offset1 = MF.getFrameInfo().getObjectOffset(FS1->getFrameIndex());
  196. return CheckOffsets(Offset0, Offset1);
  197. }
  198. // Constant pools (likely in ITCM)
  199. if (BasePseudoVal0 && BasePseudoVal1 &&
  200. BasePseudoVal0->kind() == BasePseudoVal1->kind() &&
  201. BasePseudoVal0->isConstantPool() && AssumeITCMBankConflict)
  202. return Hazard;
  203. // Is this a stack pointer-relative access? We could in general try to
  204. // use "is this the same register and is it unchanged?", but the
  205. // memory operand tracking is highly likely to have already found that.
  206. // What we're after here is bank conflicts between different objects in
  207. // the stack frame.
  208. if (!SPvalid) { // set up SP
  209. if (!getBaseOffset(L0, SP, SPOffset0) || SP->getReg().id() != ARM::SP)
  210. SP = nullptr;
  211. SPvalid = true;
  212. }
  213. if (SP) {
  214. int64_t SPOffset1;
  215. const MachineOperand *SP1;
  216. if (getBaseOffset(*L1, SP1, SPOffset1) && SP1->getReg().id() == ARM::SP)
  217. return CheckOffsets(SPOffset0, SPOffset1);
  218. }
  219. }
  220. return NoHazard;
  221. }
  222. void ARMBankConflictHazardRecognizer::Reset() { Accesses.clear(); }
  223. void ARMBankConflictHazardRecognizer::EmitInstruction(SUnit *SU) {
  224. MachineInstr &MI = *SU->getInstr();
  225. if (!MI.mayLoad() || MI.mayStore() || MI.getNumMemOperands() != 1)
  226. return;
  227. auto MO = *MI.memoperands().begin();
  228. uint64_t Size1 = MO->getSize();
  229. if (Size1 > 4)
  230. return;
  231. Accesses.push_back(&MI);
  232. }
  233. void ARMBankConflictHazardRecognizer::AdvanceCycle() { Accesses.clear(); }
  234. void ARMBankConflictHazardRecognizer::RecedeCycle() { Accesses.clear(); }