AArch64MachineScheduler.cpp 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. //===- AArch64MachineScheduler.cpp - MI Scheduler for AArch64 -------------===//
  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 "AArch64MachineScheduler.h"
  9. #include "AArch64InstrInfo.h"
  10. #include "AArch64Subtarget.h"
  11. #include "MCTargetDesc/AArch64MCTargetDesc.h"
  12. using namespace llvm;
  13. static bool needReorderStoreMI(const MachineInstr *MI) {
  14. if (!MI)
  15. return false;
  16. switch (MI->getOpcode()) {
  17. default:
  18. return false;
  19. case AArch64::STURQi:
  20. case AArch64::STRQui:
  21. if (!MI->getMF()->getSubtarget<AArch64Subtarget>().isStoreAddressAscend())
  22. return false;
  23. [[fallthrough]];
  24. case AArch64::STPQi:
  25. return AArch64InstrInfo::getLdStOffsetOp(*MI).isImm();
  26. }
  27. return false;
  28. }
  29. // Return true if two stores with same base address may overlap writes
  30. static bool mayOverlapWrite(const MachineInstr &MI0, const MachineInstr &MI1,
  31. int64_t &Off0, int64_t &Off1) {
  32. const MachineOperand &Base0 = AArch64InstrInfo::getLdStBaseOp(MI0);
  33. const MachineOperand &Base1 = AArch64InstrInfo::getLdStBaseOp(MI1);
  34. // May overlapping writes if two store instructions without same base
  35. if (!Base0.isIdenticalTo(Base1))
  36. return true;
  37. int StoreSize0 = AArch64InstrInfo::getMemScale(MI0);
  38. int StoreSize1 = AArch64InstrInfo::getMemScale(MI1);
  39. Off0 = AArch64InstrInfo::hasUnscaledLdStOffset(MI0.getOpcode())
  40. ? AArch64InstrInfo::getLdStOffsetOp(MI0).getImm()
  41. : AArch64InstrInfo::getLdStOffsetOp(MI0).getImm() * StoreSize0;
  42. Off1 = AArch64InstrInfo::hasUnscaledLdStOffset(MI1.getOpcode())
  43. ? AArch64InstrInfo::getLdStOffsetOp(MI1).getImm()
  44. : AArch64InstrInfo::getLdStOffsetOp(MI1).getImm() * StoreSize1;
  45. const MachineInstr &MI = (Off0 < Off1) ? MI0 : MI1;
  46. int Multiples = AArch64InstrInfo::isPairedLdSt(MI) ? 2 : 1;
  47. int StoreSize = AArch64InstrInfo::getMemScale(MI) * Multiples;
  48. return llabs(Off0 - Off1) < StoreSize;
  49. }
  50. bool AArch64PostRASchedStrategy::tryCandidate(SchedCandidate &Cand,
  51. SchedCandidate &TryCand) {
  52. bool OriginalResult = PostGenericScheduler::tryCandidate(Cand, TryCand);
  53. if (Cand.isValid()) {
  54. MachineInstr *Instr0 = TryCand.SU->getInstr();
  55. MachineInstr *Instr1 = Cand.SU->getInstr();
  56. if (!needReorderStoreMI(Instr0) || !needReorderStoreMI(Instr1))
  57. return OriginalResult;
  58. int64_t Off0, Off1;
  59. // With the same base address and non-overlapping writes.
  60. if (!mayOverlapWrite(*Instr0, *Instr1, Off0, Off1)) {
  61. TryCand.Reason = NodeOrder;
  62. // Order them by ascending offsets.
  63. return Off0 < Off1;
  64. }
  65. }
  66. return OriginalResult;
  67. }