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