LLVM  9.0.0svn
AArch64DeadRegisterDefinitionsPass.cpp
Go to the documentation of this file.
1 //==-- AArch64DeadRegisterDefinitions.cpp - Replace dead defs w/ zero reg --==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file When allowed by the instruction, replace a dead definition of a GPR
9 /// with the zero register. This makes the code a bit friendlier towards the
10 /// hardware's register renamer.
11 //===----------------------------------------------------------------------===//
12 
13 #include "AArch64.h"
14 #include "AArch64RegisterInfo.h"
15 #include "AArch64Subtarget.h"
16 #include "llvm/ADT/Statistic.h"
24 #include "llvm/Support/Debug.h"
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "aarch64-dead-defs"
29 
30 STATISTIC(NumDeadDefsReplaced, "Number of dead definitions replaced");
31 
32 #define AARCH64_DEAD_REG_DEF_NAME "AArch64 Dead register definitions"
33 
34 namespace {
35 class AArch64DeadRegisterDefinitions : public MachineFunctionPass {
36 private:
37  const TargetRegisterInfo *TRI;
38  const MachineRegisterInfo *MRI;
39  const TargetInstrInfo *TII;
40  bool Changed;
41  void processMachineBasicBlock(MachineBasicBlock &MBB);
42 public:
43  static char ID; // Pass identification, replacement for typeid.
44  AArch64DeadRegisterDefinitions() : MachineFunctionPass(ID) {
47  }
48 
49  bool runOnMachineFunction(MachineFunction &F) override;
50 
51  StringRef getPassName() const override { return AARCH64_DEAD_REG_DEF_NAME; }
52 
53  void getAnalysisUsage(AnalysisUsage &AU) const override {
54  AU.setPreservesCFG();
56  }
57 };
59 } // end anonymous namespace
60 
61 INITIALIZE_PASS(AArch64DeadRegisterDefinitions, "aarch64-dead-defs",
62  AARCH64_DEAD_REG_DEF_NAME, false, false)
63 
64 static bool usesFrameIndex(const MachineInstr &MI) {
65  for (const MachineOperand &MO : MI.uses())
66  if (MO.isFI())
67  return true;
68  return false;
69 }
70 
71 void AArch64DeadRegisterDefinitions::processMachineBasicBlock(
72  MachineBasicBlock &MBB) {
73  const MachineFunction &MF = *MBB.getParent();
74  for (MachineInstr &MI : MBB) {
75  if (usesFrameIndex(MI)) {
76  // We need to skip this instruction because while it appears to have a
77  // dead def it uses a frame index which might expand into a multi
78  // instruction sequence during EPI.
79  LLVM_DEBUG(dbgs() << " Ignoring, operand is frame index\n");
80  continue;
81  }
82  if (MI.definesRegister(AArch64::XZR) || MI.definesRegister(AArch64::WZR)) {
83  // It is not allowed to write to the same register (not even the zero
84  // register) twice in a single instruction.
85  LLVM_DEBUG(
86  dbgs()
87  << " Ignoring, XZR or WZR already used by the instruction\n");
88  continue;
89  }
90 
91  if (atomicBarrierDroppedOnZero(MI.getOpcode())) {
92  LLVM_DEBUG(dbgs() << " Ignoring, semantics change with xzr/wzr.\n");
93  continue;
94  }
95 
96  const MCInstrDesc &Desc = MI.getDesc();
97  for (int I = 0, E = Desc.getNumDefs(); I != E; ++I) {
98  MachineOperand &MO = MI.getOperand(I);
99  if (!MO.isReg() || !MO.isDef())
100  continue;
101  // We should not have any relevant physreg defs that are replacable by
102  // zero before register allocation. So we just check for dead vreg defs.
103  unsigned Reg = MO.getReg();
105  (!MO.isDead() && !MRI->use_nodbg_empty(Reg)))
106  continue;
107  assert(!MO.isImplicit() && "Unexpected implicit def!");
108  LLVM_DEBUG(dbgs() << " Dead def operand #" << I << " in:\n ";
109  MI.print(dbgs()));
110  // Be careful not to change the register if it's a tied operand.
111  if (MI.isRegTiedToUseOperand(I)) {
112  LLVM_DEBUG(dbgs() << " Ignoring, def is tied operand.\n");
113  continue;
114  }
115  const TargetRegisterClass *RC = TII->getRegClass(Desc, I, TRI, MF);
116  unsigned NewReg;
117  if (RC == nullptr) {
118  LLVM_DEBUG(dbgs() << " Ignoring, register is not a GPR.\n");
119  continue;
120  } else if (RC->contains(AArch64::WZR))
121  NewReg = AArch64::WZR;
122  else if (RC->contains(AArch64::XZR))
123  NewReg = AArch64::XZR;
124  else {
125  LLVM_DEBUG(dbgs() << " Ignoring, register is not a GPR.\n");
126  continue;
127  }
128  LLVM_DEBUG(dbgs() << " Replacing with zero register. New:\n ");
129  MO.setReg(NewReg);
130  MO.setIsDead();
131  LLVM_DEBUG(MI.print(dbgs()));
132  ++NumDeadDefsReplaced;
133  Changed = true;
134  // Only replace one dead register, see check for zero register above.
135  break;
136  }
137  }
138 }
139 
140 // Scan the function for instructions that have a dead definition of a
141 // register. Replace that register with the zero register when possible.
142 bool AArch64DeadRegisterDefinitions::runOnMachineFunction(MachineFunction &MF) {
143  if (skipFunction(MF.getFunction()))
144  return false;
145 
147  TII = MF.getSubtarget().getInstrInfo();
148  MRI = &MF.getRegInfo();
149  LLVM_DEBUG(dbgs() << "***** AArch64DeadRegisterDefinitions *****\n");
150  Changed = false;
151  for (auto &MBB : MF)
152  processMachineBasicBlock(MBB);
153  return Changed;
154 }
155 
157  return new AArch64DeadRegisterDefinitions();
158 }
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:23
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.
unsigned Reg
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
void setIsDead(bool Val=true)
F(f)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
static bool atomicBarrierDroppedOnZero(unsigned Opcode)
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:284
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
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: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:63
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
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
Definition: Pass.cpp:123
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:48
#define LLVM_DEBUG(X)
Definition: Debug.h:122
bool isImplicit() const