133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org//===-- ARMOptimizeBarriersPass - two DMBs without a memory access in between,
233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org//removed one -===//
333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org//
433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org//                     The LLVM Compiler Infrastructure
533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org//
633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org// This file is distributed under the University of Illinois Open Source
733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org// License. See LICENSE.TXT for details.
833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org//
933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org//===------------------------------------------------------------------------------------------===//
1033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
1133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#include "ARM.h"
1233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#include "ARMMachineFunctionInfo.h"
1333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#include "ARMInstrInfo.h"
1433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#include "llvm/ADT/Statistic.h"
1533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#include "llvm/CodeGen/MachineFunctionPass.h"
1633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgusing namespace llvm;
1733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
1833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org#define DEBUG_TYPE "double barriers"
1933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
2033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgSTATISTIC(NumDMBsRemoved, "Number of DMBs removed");
2133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
2233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgnamespace {
2333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgclass ARMOptimizeBarriersPass : public MachineFunctionPass {
2433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgpublic:
2533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  static char ID;
2633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  ARMOptimizeBarriersPass() : MachineFunctionPass(ID) {}
2733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
2833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  bool runOnMachineFunction(MachineFunction &Fn) override;
2933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
3033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  const char *getPassName() const override {
3133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    return "optimise barriers pass";
3233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  }
3333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
3433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgprivate:
3533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org};
3633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgchar ARMOptimizeBarriersPass::ID = 0;
3733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org}
3833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
3933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org// Returns whether the instruction can safely move past a DMB instruction
4033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org// The current implementation allows this iif MI does not have any possible
4133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org// memory access
4233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgstatic bool CanMovePastDMB(const MachineInstr *MI) {
4333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  return !(MI->mayLoad() ||
4433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          MI->mayStore() ||
4533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          MI->hasUnmodeledSideEffects() ||
4633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          MI->isCall() ||
4733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          MI->isReturn());
4833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org}
4933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
5033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgbool ARMOptimizeBarriersPass::runOnMachineFunction(MachineFunction &MF) {
5133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // Vector to store the DMBs we will remove after the first iteration
5233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  std::vector<MachineInstr *> ToRemove;
5333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // DMBType is the Imm value of the first operand. It determines whether it's a
5433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // DMB ish, dmb sy, dmb osh, etc
5533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  int64_t DMBType = -1;
5633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
57594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org  // Find a dmb. If we can move it until the next dmb, tag the second one for
5833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // removal
5933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  for (auto &MBB : MF) {
6033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    // Will be true when we have seen a DMB, and not seen any instruction since
6133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    // that cannot move past a DMB
6233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    bool IsRemovableNextDMB = false;
6333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    for (auto &MI : MBB) {
6433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      if (MI.getOpcode() == ARM::DMB) {
6533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        if (IsRemovableNextDMB) {
6633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          // If the Imm of this DMB is the same as that of the last DMB, we can
6733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          // tag this second DMB for removal
6833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          if (MI.getOperand(0).getImm() == DMBType) {
6933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org            ToRemove.push_back(&MI);
7033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          } else {
7133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org            // If it has a different DMBType, we cannot remove it, but will scan
7233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org            // for the next DMB, recording this DMB's type as last seen DMB type
7333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org            DMBType = MI.getOperand(0).getImm();
7433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          }
7533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        } else {
7633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          // After we see a DMB, a next one is removable
7733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          IsRemovableNextDMB = true;
7833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org          DMBType = MI.getOperand(0).getImm();
7933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        }
8033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      } else if (!CanMovePastDMB(&MI)) {
8133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        // If we find an instruction unable to pass past a DMB, a next DMB is
8233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        // not removable
8333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        IsRemovableNextDMB = false;
8433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      }
8533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    }
8633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  }
8733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  // Remove the tagged DMB
8833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  for (auto MI : ToRemove) {
8933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    MI->eraseFromParent();
9033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    ++NumDMBsRemoved;
9133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  }
9233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
9333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org  return NumDMBsRemoved > 0;
9433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org}
9533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org
9633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org/// createARMOptimizeBarriersPass - Returns an instance of the remove double
9733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org/// barriers
9833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org/// pass.
9933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgFunctionPass *llvm::createARMOptimizeBarriersPass() {
100  return new ARMOptimizeBarriersPass();
101}
102