LLVM  4.0.0
AArch64RedundantCopyElimination.cpp
Go to the documentation of this file.
1 //=- AArch64RedundantCopyElimination.cpp - Remove useless copy for AArch64 -=//
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 // This pass removes unnecessary zero copies in BBs that are targets of
9 // cbz/cbnz instructions. For instance, the copy instruction in the code below
10 // can be removed because the CBZW jumps to BB#2 when W0 is zero.
11 // BB#1:
12 // CBZW %W0, <BB#2>
13 // BB#2:
14 // %W0 = COPY %WZR
15 // This pass should be run after register allocation.
16 //
17 // FIXME: This should be extended to handle any constant other than zero. E.g.,
18 // cmp w0, #1
19 // b.eq .BB1
20 // BB1:
21 // mov w0, #1
22 //
23 // FIXME: This could also be extended to check the whole dominance subtree below
24 // the comparison if the compile time regression is acceptable.
25 //
26 //===----------------------------------------------------------------------===//
27 
28 #include "AArch64.h"
29 #include "llvm/ADT/SetVector.h"
30 #include "llvm/ADT/Statistic.h"
34 #include "llvm/Support/Debug.h"
35 
36 using namespace llvm;
37 
38 #define DEBUG_TYPE "aarch64-copyelim"
39 
40 STATISTIC(NumCopiesRemoved, "Number of copies removed.");
41 
42 namespace {
43 class AArch64RedundantCopyElimination : public MachineFunctionPass {
44  const MachineRegisterInfo *MRI;
45  const TargetRegisterInfo *TRI;
46 
47 public:
48  static char ID;
49  AArch64RedundantCopyElimination() : MachineFunctionPass(ID) {
52  }
53  bool optimizeCopy(MachineBasicBlock *MBB);
54  bool runOnMachineFunction(MachineFunction &MF) override;
55  MachineFunctionProperties getRequiredProperties() const override {
58  }
59  StringRef getPassName() const override {
60  return "AArch64 Redundant Copy Elimination";
61  }
62 };
64 }
65 
66 INITIALIZE_PASS(AArch64RedundantCopyElimination, "aarch64-copyelim",
67  "AArch64 redundant copy elimination pass", false, false)
68 
69 static bool guaranteesZeroRegInBlock(MachineInstr &MI, MachineBasicBlock *MBB) {
70  unsigned Opc = MI.getOpcode();
71  // Check if the current basic block is the target block to which the
72  // CBZ/CBNZ instruction jumps when its Wt/Xt is zero.
73  if ((Opc == AArch64::CBZW || Opc == AArch64::CBZX) &&
74  MBB == MI.getOperand(1).getMBB())
75  return true;
76  else if ((Opc == AArch64::CBNZW || Opc == AArch64::CBNZX) &&
77  MBB != MI.getOperand(1).getMBB())
78  return true;
79 
80  return false;
81 }
82 
83 bool AArch64RedundantCopyElimination::optimizeCopy(MachineBasicBlock *MBB) {
84  // Check if the current basic block has a single predecessor.
85  if (MBB->pred_size() != 1)
86  return false;
87 
88  MachineBasicBlock *PredMBB = *MBB->pred_begin();
90  if (CompBr == PredMBB->end() || PredMBB->succ_size() != 2)
91  return false;
92 
93  ++CompBr;
94  do {
95  --CompBr;
96  if (guaranteesZeroRegInBlock(*CompBr, MBB))
97  break;
98  } while (CompBr != PredMBB->begin() && CompBr->isTerminator());
99 
100  // We've not found a CBZ/CBNZ, time to bail out.
101  if (!guaranteesZeroRegInBlock(*CompBr, MBB))
102  return false;
103 
104  unsigned TargetReg = CompBr->getOperand(0).getReg();
105  if (!TargetReg)
106  return false;
108  "Expect physical register");
109 
110  // Remember all registers aliasing with TargetReg.
111  SmallSetVector<unsigned, 8> TargetRegs;
112  for (MCRegAliasIterator AI(TargetReg, TRI, true); AI.isValid(); ++AI)
113  TargetRegs.insert(*AI);
114 
115  bool Changed = false;
116  MachineBasicBlock::iterator LastChange = MBB->begin();
117  unsigned SmallestDef = TargetReg;
118  // Remove redundant Copy instructions unless TargetReg is modified.
119  for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;) {
120  MachineInstr *MI = &*I;
121  ++I;
122  if (MI->isCopy() && MI->getOperand(0).isReg() &&
123  MI->getOperand(1).isReg()) {
124 
125  unsigned DefReg = MI->getOperand(0).getReg();
126  unsigned SrcReg = MI->getOperand(1).getReg();
127 
128  if ((SrcReg == AArch64::XZR || SrcReg == AArch64::WZR) &&
129  !MRI->isReserved(DefReg) &&
130  (TargetReg == DefReg || TRI->isSuperRegister(DefReg, TargetReg))) {
131  DEBUG(dbgs() << "Remove redundant Copy : ");
132  DEBUG((MI)->print(dbgs()));
133 
134  MI->eraseFromParent();
135  Changed = true;
136  LastChange = I;
137  NumCopiesRemoved++;
138  SmallestDef =
139  TRI->isSubRegister(SmallestDef, DefReg) ? DefReg : SmallestDef;
140  continue;
141  }
142  }
143 
144  if (MI->modifiesRegister(TargetReg, TRI))
145  break;
146  }
147 
148  if (!Changed)
149  return false;
150 
151  // Otherwise, we have to fixup the use-def chain, starting with the
152  // CBZ/CBNZ. Conservatively mark as much as we can live.
153  CompBr->clearRegisterKills(SmallestDef, TRI);
154 
155  if (none_of(TargetRegs, [&](unsigned Reg) { return MBB->isLiveIn(Reg); }))
156  MBB->addLiveIn(TargetReg);
157 
158  // Clear any kills of TargetReg between CompBr and the last removed COPY.
159  for (MachineInstr &MMI : make_range(MBB->begin(), LastChange))
160  MMI.clearRegisterKills(SmallestDef, TRI);
161 
162  return true;
163 }
164 
165 bool AArch64RedundantCopyElimination::runOnMachineFunction(
166  MachineFunction &MF) {
167  if (skipFunction(*MF.getFunction()))
168  return false;
169  TRI = MF.getSubtarget().getRegisterInfo();
170  MRI = &MF.getRegInfo();
171  bool Changed = false;
172  for (MachineBasicBlock &MBB : MF)
173  Changed |= optimizeCopy(&MBB);
174  return Changed;
175 }
176 
178  return new AArch64RedundantCopyElimination();
179 }
unsigned succ_size() const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
STATISTIC(NumFunctions,"Total number of functions")
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
void initializeAArch64RedundantCopyEliminationPass(PassRegistry &)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:750
Reg
All possible values of the reg field in the ModR/M byte.
FunctionPass * createAArch64RedundantCopyEliminationPass()
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:136
MachineBasicBlock * MBB
iterator getLastNonDebugInstr()
Returns an iterator to the last non-debug instruction in the basic block, or end().
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
void addLiveIn(MCPhysReg PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
unsigned const MachineRegisterInfo * MRI
INITIALIZE_PASS(AArch64RedundantCopyElimination,"aarch64-copyelim","AArch64 redundant copy elimination pass", false, false) static bool guaranteesZeroRegInBlock(MachineInstr &MI
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:279
bool isCopy() const
Definition: MachineInstr.h:807
MCRegAliasIterator enumerates all registers aliasing Reg.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
A SetVector that performs no allocations if smaller than a certain size.
Definition: SetVector.h:292
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
MachineFunctionProperties & set(Property P)
Representation of each machine instruction.
Definition: MachineInstr.h:52
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
#define I(x, y, z)
Definition: MD5.cpp:54
bool isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define DEBUG(X)
Definition: Debug.h:100
IRTranslator LLVM IR MI
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
unsigned pred_size() const
bool modifiesRegister(unsigned Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register...
Definition: MachineInstr.h:903
Properties which a MachineFunction may have at a given point in time.