ARMOptimizeBarriersPass.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. //===-- ARMOptimizeBarriersPass - two DMBs without a memory access in between,
  2. //removed one -===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===------------------------------------------------------------------------------------------===//
  9. #include "ARM.h"
  10. #include "ARMInstrInfo.h"
  11. #include "ARMMachineFunctionInfo.h"
  12. #include "llvm/ADT/Statistic.h"
  13. #include "llvm/CodeGen/MachineFunctionPass.h"
  14. using namespace llvm;
  15. #define DEBUG_TYPE "double barriers"
  16. STATISTIC(NumDMBsRemoved, "Number of DMBs removed");
  17. namespace {
  18. class ARMOptimizeBarriersPass : public MachineFunctionPass {
  19. public:
  20. static char ID;
  21. ARMOptimizeBarriersPass() : MachineFunctionPass(ID) {}
  22. bool runOnMachineFunction(MachineFunction &Fn) override;
  23. MachineFunctionProperties getRequiredProperties() const override {
  24. return MachineFunctionProperties().set(
  25. MachineFunctionProperties::Property::NoVRegs);
  26. }
  27. StringRef getPassName() const override { return "optimise barriers pass"; }
  28. };
  29. char ARMOptimizeBarriersPass::ID = 0;
  30. }
  31. // Returns whether the instruction can safely move past a DMB instruction
  32. // The current implementation allows this iif MI does not have any possible
  33. // memory access
  34. static bool CanMovePastDMB(const MachineInstr *MI) {
  35. return !(MI->mayLoad() ||
  36. MI->mayStore() ||
  37. MI->hasUnmodeledSideEffects() ||
  38. MI->isCall() ||
  39. MI->isReturn());
  40. }
  41. bool ARMOptimizeBarriersPass::runOnMachineFunction(MachineFunction &MF) {
  42. if (skipFunction(MF.getFunction()))
  43. return false;
  44. // Vector to store the DMBs we will remove after the first iteration
  45. std::vector<MachineInstr *> ToRemove;
  46. // DMBType is the Imm value of the first operand. It determines whether it's a
  47. // DMB ish, dmb sy, dmb osh, etc
  48. int64_t DMBType = -1;
  49. // Find a dmb. If we can move it until the next dmb, tag the second one for
  50. // removal
  51. for (auto &MBB : MF) {
  52. // Will be true when we have seen a DMB, and not seen any instruction since
  53. // that cannot move past a DMB
  54. bool IsRemovableNextDMB = false;
  55. for (auto &MI : MBB) {
  56. if (MI.getOpcode() == ARM::DMB) {
  57. if (IsRemovableNextDMB) {
  58. // If the Imm of this DMB is the same as that of the last DMB, we can
  59. // tag this second DMB for removal
  60. if (MI.getOperand(0).getImm() == DMBType) {
  61. ToRemove.push_back(&MI);
  62. } else {
  63. // If it has a different DMBType, we cannot remove it, but will scan
  64. // for the next DMB, recording this DMB's type as last seen DMB type
  65. DMBType = MI.getOperand(0).getImm();
  66. }
  67. } else {
  68. // After we see a DMB, a next one is removable
  69. IsRemovableNextDMB = true;
  70. DMBType = MI.getOperand(0).getImm();
  71. }
  72. } else if (!CanMovePastDMB(&MI)) {
  73. // If we find an instruction unable to pass past a DMB, a next DMB is
  74. // not removable
  75. IsRemovableNextDMB = false;
  76. }
  77. }
  78. }
  79. bool Changed = false;
  80. // Remove the tagged DMB
  81. for (auto MI : ToRemove) {
  82. MI->eraseFromParent();
  83. ++NumDMBsRemoved;
  84. Changed = true;
  85. }
  86. return Changed;
  87. }
  88. /// createARMOptimizeBarriersPass - Returns an instance of the remove double
  89. /// barriers
  90. /// pass.
  91. FunctionPass *llvm::createARMOptimizeBarriersPass() {
  92. return new ARMOptimizeBarriersPass();
  93. }