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