Line data Source code
1 : //===-- ARMOptimizeBarriersPass - two DMBs without a memory access in between,
2 : //removed one -===//
3 : //
4 : // The LLVM Compiler Infrastructure
5 : //
6 : // This file is distributed under the University of Illinois Open Source
7 : // License. See LICENSE.TXT for details.
8 : //
9 : //===------------------------------------------------------------------------------------------===//
10 :
11 : #include "ARM.h"
12 : #include "ARMInstrInfo.h"
13 : #include "ARMMachineFunctionInfo.h"
14 : #include "llvm/ADT/Statistic.h"
15 : #include "llvm/CodeGen/MachineFunctionPass.h"
16 : using namespace llvm;
17 :
18 : #define DEBUG_TYPE "double barriers"
19 :
20 : STATISTIC(NumDMBsRemoved, "Number of DMBs removed");
21 :
22 : namespace {
23 : class ARMOptimizeBarriersPass : public MachineFunctionPass {
24 : public:
25 : static char ID;
26 2569 : ARMOptimizeBarriersPass() : MachineFunctionPass(ID) {}
27 :
28 : bool runOnMachineFunction(MachineFunction &Fn) override;
29 :
30 2558 : MachineFunctionProperties getRequiredProperties() const override {
31 2558 : return MachineFunctionProperties().set(
32 2558 : MachineFunctionProperties::Property::NoVRegs);
33 : }
34 :
35 2557 : StringRef getPassName() const override { return "optimise barriers pass"; }
36 : };
37 : char ARMOptimizeBarriersPass::ID = 0;
38 : }
39 :
40 : // Returns whether the instruction can safely move past a DMB instruction
41 : // The current implementation allows this iif MI does not have any possible
42 : // memory access
43 133231 : static bool CanMovePastDMB(const MachineInstr *MI) {
44 327874 : return !(MI->mayLoad() ||
45 209972 : MI->mayStore() ||
46 186830 : MI->hasUnmodeledSideEffects() ||
47 : MI->isCall() ||
48 133231 : MI->isReturn());
49 : }
50 :
51 13376 : bool ARMOptimizeBarriersPass::runOnMachineFunction(MachineFunction &MF) {
52 13376 : if (skipFunction(MF.getFunction()))
53 : return false;
54 :
55 : // Vector to store the DMBs we will remove after the first iteration
56 : std::vector<MachineInstr *> ToRemove;
57 : // DMBType is the Imm value of the first operand. It determines whether it's a
58 : // DMB ish, dmb sy, dmb osh, etc
59 : int64_t DMBType = -1;
60 :
61 : // Find a dmb. If we can move it until the next dmb, tag the second one for
62 : // removal
63 30950 : for (auto &MBB : MF) {
64 : // Will be true when we have seen a DMB, and not seen any instruction since
65 : // that cannot move past a DMB
66 : bool IsRemovableNextDMB = false;
67 150924 : for (auto &MI : MBB) {
68 266684 : if (MI.getOpcode() == ARM::DMB) {
69 111 : if (IsRemovableNextDMB) {
70 : // If the Imm of this DMB is the same as that of the last DMB, we can
71 : // tag this second DMB for removal
72 6 : if (MI.getOperand(0).getImm() == DMBType) {
73 5 : ToRemove.push_back(&MI);
74 : } else {
75 : // If it has a different DMBType, we cannot remove it, but will scan
76 : // for the next DMB, recording this DMB's type as last seen DMB type
77 : DMBType = MI.getOperand(0).getImm();
78 : }
79 : } else {
80 : // After we see a DMB, a next one is removable
81 : IsRemovableNextDMB = true;
82 105 : DMBType = MI.getOperand(0).getImm();
83 : }
84 133231 : } else if (!CanMovePastDMB(&MI)) {
85 : // If we find an instruction unable to pass past a DMB, a next DMB is
86 : // not removable
87 : IsRemovableNextDMB = false;
88 : }
89 : }
90 : }
91 : bool Changed = false;
92 : // Remove the tagged DMB
93 13373 : for (auto MI : ToRemove) {
94 5 : MI->eraseFromParent();
95 : ++NumDMBsRemoved;
96 : Changed = true;
97 : }
98 :
99 : return Changed;
100 : }
101 :
102 : /// createARMOptimizeBarriersPass - Returns an instance of the remove double
103 : /// barriers
104 : /// pass.
105 2569 : FunctionPass *llvm::createARMOptimizeBarriersPass() {
106 2569 : return new ARMOptimizeBarriersPass();
107 : }
|