LLVM  8.0.1
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  LLVM_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  LLVM_DEBUG(
146  dbgs()
147  << " Ignoring, XZR or WZR already used by the instruction\n");
148  continue;
149  }
150 
151  if (shouldSkip(MI, MF)) {
152  LLVM_DEBUG(dbgs() << " Ignoring, Atomic instruction with acquire "
153  "semantics using WZR/XZR\n");
154  continue;
155  }
156 
157  const MCInstrDesc &Desc = MI.getDesc();
158  for (int I = 0, E = Desc.getNumDefs(); I != E; ++I) {
159  MachineOperand &MO = MI.getOperand(I);
160  if (!MO.isReg() || !MO.isDef())
161  continue;
162  // We should not have any relevant physreg defs that are replacable by
163  // zero before register allocation. So we just check for dead vreg defs.
164  unsigned Reg = MO.getReg();
166  (!MO.isDead() && !MRI->use_nodbg_empty(Reg)))
167  continue;
168  assert(!MO.isImplicit() && "Unexpected implicit def!");
169  LLVM_DEBUG(dbgs() << " Dead def operand #" << I << " in:\n ";
170  MI.print(dbgs()));
171  // Be careful not to change the register if it's a tied operand.
172  if (MI.isRegTiedToUseOperand(I)) {
173  LLVM_DEBUG(dbgs() << " Ignoring, def is tied operand.\n");
174  continue;
175  }
176  const TargetRegisterClass *RC = TII->getRegClass(Desc, I, TRI, MF);
177  unsigned NewReg;
178  if (RC == nullptr) {
179  LLVM_DEBUG(dbgs() << " Ignoring, register is not a GPR.\n");
180  continue;
181  } else if (RC->contains(AArch64::WZR))
182  NewReg = AArch64::WZR;
183  else if (RC->contains(AArch64::XZR))
184  NewReg = AArch64::XZR;
185  else {
186  LLVM_DEBUG(dbgs() << " Ignoring, register is not a GPR.\n");
187  continue;
188  }
189  LLVM_DEBUG(dbgs() << " Replacing with zero register. New:\n ");
190  MO.setReg(NewReg);
191  MO.setIsDead();
192  LLVM_DEBUG(MI.print(dbgs()));
193  ++NumDeadDefsReplaced;
194  Changed = true;
195  // Only replace one dead register, see check for zero register above.
196  break;
197  }
198  }
199 }
200 
201 // Scan the function for instructions that have a dead definition of a
202 // register. Replace that register with the zero register when possible.
203 bool AArch64DeadRegisterDefinitions::runOnMachineFunction(MachineFunction &MF) {
204  if (skipFunction(MF.getFunction()))
205  return false;
206 
208  TII = MF.getSubtarget().getInstrInfo();
209  MRI = &MF.getRegInfo();
210  LLVM_DEBUG(dbgs() << "***** AArch64DeadRegisterDefinitions *****\n");
211  Changed = false;
212  for (auto &MBB : MF)
213  processMachineBasicBlock(MBB);
214  return Changed;
215 }
216 
218  return new AArch64DeadRegisterDefinitions();
219 }
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.
This class represents lattice values for constants.
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:164
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.
unsigned Reg
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
void setIsDead(bool Val=true)
F(f)
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
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Definition: MachineInstr.h:406
virtual const TargetInstrInfo * getInstrInfo() const
TargetInstrInfo - Interface to description of machine instruction set.
unsigned const MachineRegisterInfo * MRI
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
Definition: MachineInstr.h:516
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.
void print(raw_ostream &OS, bool IsStandalone=true, bool SkipOpers=false, bool SkipDebugLoc=false, bool AddNewLine=true, const TargetInstrInfo *TII=nullptr) const
Print this MI to OS.
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:226
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:286
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
#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:64
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...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
aarch64 promote const
void initializeAArch64DeadRegisterDefinitionsPass(PassRegistry &)
IRTranslator LLVM IR MI
FunctionPass * createAArch64DeadRegisterDefinitions()
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
#define LLVM_DEBUG(X)
Definition: Debug.h:123
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:414
bool isImplicit() const