LLVM  6.0.0svn
AArch64DeadRegisterDefinitionsPass.cpp
Go to the documentation of this file.
1 //==-- AArch64DeadRegisterDefinitions.cpp - Replace dead defs w/ zero reg --==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file When allowed by the instruction, replace a dead definition of a GPR
10 /// with the zero register. This makes the code a bit friendlier towards the
11 /// hardware's register renamer.
12 //===----------------------------------------------------------------------===//
13 
14 #include "AArch64.h"
15 #include "AArch64RegisterInfo.h"
16 #include "AArch64Subtarget.h"
17 #include "llvm/ADT/Statistic.h"
25 #include "llvm/Support/Debug.h"
27 using namespace llvm;
28 
29 #define DEBUG_TYPE "aarch64-dead-defs"
30 
31 STATISTIC(NumDeadDefsReplaced, "Number of dead definitions replaced");
32 
33 #define AARCH64_DEAD_REG_DEF_NAME "AArch64 Dead register definitions"
34 
35 namespace {
36 class AArch64DeadRegisterDefinitions : public MachineFunctionPass {
37 private:
38  const TargetRegisterInfo *TRI;
39  const MachineRegisterInfo *MRI;
40  const TargetInstrInfo *TII;
41  bool Changed;
42  void processMachineBasicBlock(MachineBasicBlock &MBB);
43 public:
44  static char ID; // Pass identification, replacement for typeid.
45  AArch64DeadRegisterDefinitions() : MachineFunctionPass(ID) {
48  }
49 
50  bool runOnMachineFunction(MachineFunction &F) override;
51 
52  StringRef getPassName() const override { return AARCH64_DEAD_REG_DEF_NAME; }
53 
54  void getAnalysisUsage(AnalysisUsage &AU) const override {
55  AU.setPreservesCFG();
57  }
58 
59  bool shouldSkip(const MachineInstr &MI, const MachineFunction &MF) const;
60 };
62 } // end anonymous namespace
63 
64 INITIALIZE_PASS(AArch64DeadRegisterDefinitions, "aarch64-dead-defs",
65  AARCH64_DEAD_REG_DEF_NAME, false, false)
66 
67 static bool usesFrameIndex(const MachineInstr &MI) {
68  for (const MachineOperand &MO : MI.uses())
69  if (MO.isFI())
70  return true;
71  return false;
72 }
73 
74 bool
75 AArch64DeadRegisterDefinitions::shouldSkip(const MachineInstr &MI,
76  const MachineFunction &MF) const {
78  return false;
79 
80 #define CASE_AARCH64_ATOMIC_(PREFIX) \
81  case AArch64::PREFIX##X: \
82  case AArch64::PREFIX##W: \
83  case AArch64::PREFIX##H: \
84  case AArch64::PREFIX##B
85 
86  for (const MachineMemOperand *MMO : MI.memoperands()) {
87  if (MMO->isAtomic()) {
88  unsigned Opcode = MI.getOpcode();
89  switch (Opcode) {
90  default:
91  return false;
92  break;
93 
94  CASE_AARCH64_ATOMIC_(LDADDA):
95  CASE_AARCH64_ATOMIC_(LDADDAL):
96 
97  CASE_AARCH64_ATOMIC_(LDCLRA):
98  CASE_AARCH64_ATOMIC_(LDCLRAL):
99 
100  CASE_AARCH64_ATOMIC_(LDEORA):
101  CASE_AARCH64_ATOMIC_(LDEORAL):
102 
103  CASE_AARCH64_ATOMIC_(LDSETA):
104  CASE_AARCH64_ATOMIC_(LDSETAL):
105 
106  CASE_AARCH64_ATOMIC_(LDSMAXA):
107  CASE_AARCH64_ATOMIC_(LDSMAXAL):
108 
109  CASE_AARCH64_ATOMIC_(LDSMINA):
110  CASE_AARCH64_ATOMIC_(LDSMINAL):
111 
112  CASE_AARCH64_ATOMIC_(LDUMAXA):
113  CASE_AARCH64_ATOMIC_(LDUMAXAL):
114 
115  CASE_AARCH64_ATOMIC_(LDUMINA):
116  CASE_AARCH64_ATOMIC_(LDUMINAL):
117 
118  CASE_AARCH64_ATOMIC_(SWPA):
119  CASE_AARCH64_ATOMIC_(SWPAL):
120  return true;
121  break;
122  }
123  }
124  }
125 
126 #undef CASE_AARCH64_ATOMIC_
127 
128  return false;
129 }
130 
131 void AArch64DeadRegisterDefinitions::processMachineBasicBlock(
132  MachineBasicBlock &MBB) {
133  const MachineFunction &MF = *MBB.getParent();
134  for (MachineInstr &MI : MBB) {
135  if (usesFrameIndex(MI)) {
136  // We need to skip this instruction because while it appears to have a
137  // dead def it uses a frame index which might expand into a multi
138  // instruction sequence during EPI.
139  DEBUG(dbgs() << " Ignoring, operand is frame index\n");
140  continue;
141  }
142  if (MI.definesRegister(AArch64::XZR) || MI.definesRegister(AArch64::WZR)) {
143  // It is not allowed to write to the same register (not even the zero
144  // register) twice in a single instruction.
145  DEBUG(dbgs() << " Ignoring, XZR or WZR already used by the instruction\n");
146  continue;
147  }
148 
149  if (shouldSkip(MI, MF)) {
150  DEBUG(dbgs() << " Ignoring, Atomic instruction with acquire semantics using WZR/XZR\n");
151  continue;
152  }
153 
154  const MCInstrDesc &Desc = MI.getDesc();
155  for (int I = 0, E = Desc.getNumDefs(); I != E; ++I) {
156  MachineOperand &MO = MI.getOperand(I);
157  if (!MO.isReg() || !MO.isDef())
158  continue;
159  // We should not have any relevant physreg defs that are replacable by
160  // zero before register allocation. So we just check for dead vreg defs.
161  unsigned Reg = MO.getReg();
163  (!MO.isDead() && !MRI->use_nodbg_empty(Reg)))
164  continue;
165  assert(!MO.isImplicit() && "Unexpected implicit def!");
166  DEBUG(dbgs() << " Dead def operand #" << I << " in:\n ";
167  MI.print(dbgs()));
168  // Be careful not to change the register if it's a tied operand.
169  if (MI.isRegTiedToUseOperand(I)) {
170  DEBUG(dbgs() << " Ignoring, def is tied operand.\n");
171  continue;
172  }
173  const TargetRegisterClass *RC = TII->getRegClass(Desc, I, TRI, MF);
174  unsigned NewReg;
175  if (RC == nullptr) {
176  DEBUG(dbgs() << " Ignoring, register is not a GPR.\n");
177  continue;
178  } else if (RC->contains(AArch64::WZR))
179  NewReg = AArch64::WZR;
180  else if (RC->contains(AArch64::XZR))
181  NewReg = AArch64::XZR;
182  else {
183  DEBUG(dbgs() << " Ignoring, register is not a GPR.\n");
184  continue;
185  }
186  DEBUG(dbgs() << " Replacing with zero register. New:\n ");
187  MO.setReg(NewReg);
188  MO.setIsDead();
189  DEBUG(MI.print(dbgs()));
190  ++NumDeadDefsReplaced;
191  Changed = true;
192  // Only replace one dead register, see check for zero register above.
193  break;
194  }
195  }
196 }
197 
198 // Scan the function for instructions that have a dead definition of a
199 // register. Replace that register with the zero register when possible.
200 bool AArch64DeadRegisterDefinitions::runOnMachineFunction(MachineFunction &MF) {
201  if (skipFunction(*MF.getFunction()))
202  return false;
203 
204  TRI = MF.getSubtarget().getRegisterInfo();
205  TII = MF.getSubtarget().getInstrInfo();
206  MRI = &MF.getRegInfo();
207  DEBUG(dbgs() << "***** AArch64DeadRegisterDefinitions *****\n");
208  Changed = false;
209  for (auto &MBB : MF)
210  processMachineBasicBlock(MBB);
211  return Changed;
212 }
213 
215  return new AArch64DeadRegisterDefinitions();
216 }
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
bool contains(unsigned Reg) const
Return true if the specified register is included in this register class.
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
#define CASE_AARCH64_ATOMIC_(PREFIX)
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:163
unsigned getReg() const
getReg - Returns the register number.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
STATISTIC(NumFunctions, "Total number of functions")
void setIsDead(bool Val=true)
F(f)
iterator_range< mmo_iterator > memoperands()
Definition: MachineInstr.h:396
A description of a memory reference used in the backend.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
Reg
All possible values of the reg field in the ModR/M byte.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:290
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Definition: MachineInstr.h:287
virtual const TargetInstrInfo * getInstrInfo() const
TargetInstrInfo - Interface to description of machine instruction set.
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr fully defines the specified register.
Definition: MachineInstr.h:957
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
MachineOperand class - Representation of each machine instruction operand.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
Definition: MCInstrDesc.h:225
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:285
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
#define AARCH64_DEAD_REG_DEF_NAME
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:59
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
INITIALIZE_PASS(AArch64DeadRegisterDefinitions, "aarch64-dead-defs", AARCH64_DEAD_REG_DEF_NAME, false, false) static bool usesFrameIndex(const MachineInstr &MI)
void setReg(unsigned Reg)
Change the register this operand corresponds to.
#define I(x, y, z)
Definition: MD5.cpp:58
bool isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx=nullptr) const
Given the index of a register def operand, check if the register def is tied to a source operand...
void print(raw_ostream &OS, bool SkipOpers=false, bool SkipDebugLoc=false, const TargetInstrInfo *TII=nullptr) const
Debugging supportPrint this MI to OS.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
aarch64 promote const
void initializeAArch64DeadRegisterDefinitionsPass(PassRegistry &)
#define DEBUG(X)
Definition: Debug.h:118
IRTranslator LLVM IR MI
FunctionPass * createAArch64DeadRegisterDefinitions()
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:295
bool isImplicit() const