xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/ARMOptimizeBarriersPass.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===-- ARMOptimizeBarriersPass - two DMBs without a memory access in between,
20b57cec5SDimitry Andric //removed one -===//
30b57cec5SDimitry Andric //
40b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric //
80b57cec5SDimitry Andric //===------------------------------------------------------------------------------------------===//
90b57cec5SDimitry Andric 
100b57cec5SDimitry Andric #include "ARM.h"
110b57cec5SDimitry Andric #include "ARMInstrInfo.h"
120b57cec5SDimitry Andric #include "ARMMachineFunctionInfo.h"
130b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
140b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
150b57cec5SDimitry Andric using namespace llvm;
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #define DEBUG_TYPE "double barriers"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric STATISTIC(NumDMBsRemoved, "Number of DMBs removed");
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric namespace {
220b57cec5SDimitry Andric class ARMOptimizeBarriersPass : public MachineFunctionPass {
230b57cec5SDimitry Andric public:
240b57cec5SDimitry Andric   static char ID;
ARMOptimizeBarriersPass()250b57cec5SDimitry Andric   ARMOptimizeBarriersPass() : MachineFunctionPass(ID) {}
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &Fn) override;
280b57cec5SDimitry Andric 
getRequiredProperties() const290b57cec5SDimitry Andric   MachineFunctionProperties getRequiredProperties() const override {
300b57cec5SDimitry Andric     return MachineFunctionProperties().set(
310b57cec5SDimitry Andric         MachineFunctionProperties::Property::NoVRegs);
320b57cec5SDimitry Andric   }
330b57cec5SDimitry Andric 
getPassName() const340b57cec5SDimitry Andric   StringRef getPassName() const override { return "optimise barriers pass"; }
350b57cec5SDimitry Andric };
360b57cec5SDimitry Andric char ARMOptimizeBarriersPass::ID = 0;
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric // Returns whether the instruction can safely move past a DMB instruction
400b57cec5SDimitry Andric // The current implementation allows this iif MI does not have any possible
410b57cec5SDimitry Andric // memory access
CanMovePastDMB(const MachineInstr * MI)420b57cec5SDimitry Andric static bool CanMovePastDMB(const MachineInstr *MI) {
430b57cec5SDimitry Andric   return !(MI->mayLoad() ||
440b57cec5SDimitry Andric           MI->mayStore() ||
450b57cec5SDimitry Andric           MI->hasUnmodeledSideEffects() ||
460b57cec5SDimitry Andric           MI->isCall() ||
470b57cec5SDimitry Andric           MI->isReturn());
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)500b57cec5SDimitry Andric bool ARMOptimizeBarriersPass::runOnMachineFunction(MachineFunction &MF) {
510b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
520b57cec5SDimitry Andric     return false;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   // Vector to store the DMBs we will remove after the first iteration
550b57cec5SDimitry Andric   std::vector<MachineInstr *> ToRemove;
560b57cec5SDimitry Andric   // DMBType is the Imm value of the first operand. It determines whether it's a
570b57cec5SDimitry Andric   // DMB ish, dmb sy, dmb osh, etc
580b57cec5SDimitry Andric   int64_t DMBType = -1;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   // Find a dmb. If we can move it until the next dmb, tag the second one for
610b57cec5SDimitry Andric   // removal
620b57cec5SDimitry Andric   for (auto &MBB : MF) {
630b57cec5SDimitry Andric     // Will be true when we have seen a DMB, and not seen any instruction since
640b57cec5SDimitry Andric     // that cannot move past a DMB
650b57cec5SDimitry Andric     bool IsRemovableNextDMB = false;
660b57cec5SDimitry Andric     for (auto &MI : MBB) {
670b57cec5SDimitry Andric       if (MI.getOpcode() == ARM::DMB) {
680b57cec5SDimitry Andric         if (IsRemovableNextDMB) {
690b57cec5SDimitry Andric           // If the Imm of this DMB is the same as that of the last DMB, we can
700b57cec5SDimitry Andric           // tag this second DMB for removal
710b57cec5SDimitry Andric           if (MI.getOperand(0).getImm() == DMBType) {
720b57cec5SDimitry Andric             ToRemove.push_back(&MI);
730b57cec5SDimitry Andric           } else {
740b57cec5SDimitry Andric             // If it has a different DMBType, we cannot remove it, but will scan
750b57cec5SDimitry Andric             // for the next DMB, recording this DMB's type as last seen DMB type
760b57cec5SDimitry Andric             DMBType = MI.getOperand(0).getImm();
770b57cec5SDimitry Andric           }
780b57cec5SDimitry Andric         } else {
790b57cec5SDimitry Andric           // After we see a DMB, a next one is removable
800b57cec5SDimitry Andric           IsRemovableNextDMB = true;
810b57cec5SDimitry Andric           DMBType = MI.getOperand(0).getImm();
820b57cec5SDimitry Andric         }
830b57cec5SDimitry Andric       } else if (!CanMovePastDMB(&MI)) {
840b57cec5SDimitry Andric         // If we find an instruction unable to pass past a DMB, a next DMB is
850b57cec5SDimitry Andric         // not removable
860b57cec5SDimitry Andric         IsRemovableNextDMB = false;
870b57cec5SDimitry Andric       }
880b57cec5SDimitry Andric     }
890b57cec5SDimitry Andric   }
900b57cec5SDimitry Andric   bool Changed = false;
910b57cec5SDimitry Andric   // Remove the tagged DMB
92*bdd1243dSDimitry Andric   for (auto *MI : ToRemove) {
930b57cec5SDimitry Andric     MI->eraseFromParent();
940b57cec5SDimitry Andric     ++NumDMBsRemoved;
950b57cec5SDimitry Andric     Changed = true;
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   return Changed;
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric /// createARMOptimizeBarriersPass - Returns an instance of the remove double
1020b57cec5SDimitry Andric /// barriers
1030b57cec5SDimitry Andric /// pass.
createARMOptimizeBarriersPass()1040b57cec5SDimitry Andric FunctionPass *llvm::createARMOptimizeBarriersPass() {
1050b57cec5SDimitry Andric   return new ARMOptimizeBarriersPass();
1060b57cec5SDimitry Andric }
107