brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.4 KiB · b2708ec Raw
105 lines · cpp
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-exception7//8//===------------------------------------------------------------------------------------------===//9 10#include "ARM.h"11#include "ARMInstrInfo.h"12#include "llvm/ADT/Statistic.h"13#include "llvm/CodeGen/MachineFunctionPass.h"14using namespace llvm;15 16#define DEBUG_TYPE "double barriers"17 18STATISTIC(NumDMBsRemoved, "Number of DMBs removed");19 20namespace {21class ARMOptimizeBarriersPass : public MachineFunctionPass {22public:23  static char ID;24  ARMOptimizeBarriersPass() : MachineFunctionPass(ID) {}25 26  bool runOnMachineFunction(MachineFunction &Fn) override;27 28  MachineFunctionProperties getRequiredProperties() const override {29    return MachineFunctionProperties().setNoVRegs();30  }31 32  StringRef getPassName() const override { return "optimise barriers pass"; }33};34char ARMOptimizeBarriersPass::ID = 0;35}36 37// Returns whether the instruction can safely move past a DMB instruction38// The current implementation allows this iif MI does not have any possible39// memory access40static bool CanMovePastDMB(const MachineInstr *MI) {41  return !(MI->mayLoad() ||42          MI->mayStore() ||43          MI->hasUnmodeledSideEffects() ||44          MI->isCall() ||45          MI->isReturn());46}47 48bool ARMOptimizeBarriersPass::runOnMachineFunction(MachineFunction &MF) {49  if (skipFunction(MF.getFunction()))50    return false;51 52  // Vector to store the DMBs we will remove after the first iteration53  std::vector<MachineInstr *> ToRemove;54  // DMBType is the Imm value of the first operand. It determines whether it's a55  // DMB ish, dmb sy, dmb osh, etc56  int64_t DMBType = -1;57 58  // Find a dmb. If we can move it until the next dmb, tag the second one for59  // removal60  for (auto &MBB : MF) {61    // Will be true when we have seen a DMB, and not seen any instruction since62    // that cannot move past a DMB63    bool IsRemovableNextDMB = false;64    for (auto &MI : MBB) {65      if (MI.getOpcode() == ARM::DMB) {66        if (IsRemovableNextDMB) {67          // If the Imm of this DMB is the same as that of the last DMB, we can68          // tag this second DMB for removal69          if (MI.getOperand(0).getImm() == DMBType) {70            ToRemove.push_back(&MI);71          } else {72            // If it has a different DMBType, we cannot remove it, but will scan73            // for the next DMB, recording this DMB's type as last seen DMB type74            DMBType = MI.getOperand(0).getImm();75          }76        } else {77          // After we see a DMB, a next one is removable78          IsRemovableNextDMB = true;79          DMBType = MI.getOperand(0).getImm();80        }81      } else if (!CanMovePastDMB(&MI)) {82        // If we find an instruction unable to pass past a DMB, a next DMB is83        // not removable84        IsRemovableNextDMB = false;85      }86    }87  }88  bool Changed = false;89  // Remove the tagged DMB90  for (auto *MI : ToRemove) {91    MI->eraseFromParent();92    ++NumDMBsRemoved;93    Changed = true;94  }95 96  return Changed;97}98 99/// createARMOptimizeBarriersPass - Returns an instance of the remove double100/// barriers101/// pass.102FunctionPass *llvm::createARMOptimizeBarriersPass() {103  return new ARMOptimizeBarriersPass();104}105