LLVM  8.0.1
BPFMIPeephole.cpp
Go to the documentation of this file.
1 //===-------------- BPFMIPeephole.cpp - MI Peephole Cleanups -------------===//
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 //
10 // This pass performs peephole optimizations to cleanup ugly code sequences at
11 // MachineInstruction layer.
12 //
13 // Currently, there are two optimizations implemented:
14 // - One pre-RA MachineSSA pass to eliminate type promotion sequences, those
15 // zero extend 32-bit subregisters to 64-bit registers, if the compiler
16 // could prove the subregisters is defined by 32-bit operations in which
17 // case the upper half of the underlying 64-bit registers were zeroed
18 // implicitly.
19 //
20 // - One post-RA PreEmit pass to do final cleanup on some redundant
21 // instructions generated due to bad RA on subregister.
22 //===----------------------------------------------------------------------===//
23 
24 #include "BPF.h"
25 #include "BPFInstrInfo.h"
26 #include "BPFTargetMachine.h"
27 #include "llvm/ADT/Statistic.h"
30 
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "bpf-mi-zext-elim"
34 
35 STATISTIC(ZExtElemNum, "Number of zero extension shifts eliminated");
36 
37 namespace {
38 
39 struct BPFMIPeephole : public MachineFunctionPass {
40 
41  static char ID;
42  const BPFInstrInfo *TII;
43  MachineFunction *MF;
45 
46  BPFMIPeephole() : MachineFunctionPass(ID) {
48  }
49 
50 private:
51  // Initialize class variables.
52  void initialize(MachineFunction &MFParm);
53 
54  bool isMovFrom32Def(MachineInstr *MovMI);
55  bool eliminateZExtSeq(void);
56 
57 public:
58 
59  // Main entry point for this pass.
60  bool runOnMachineFunction(MachineFunction &MF) override {
61  if (skipFunction(MF.getFunction()))
62  return false;
63 
64  initialize(MF);
65 
66  return eliminateZExtSeq();
67  }
68 };
69 
70 // Initialize class variables.
72  MF = &MFParm;
73  MRI = &MF->getRegInfo();
74  TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
75  LLVM_DEBUG(dbgs() << "*** BPF MachineSSA peephole pass ***\n\n");
76 }
77 
78 bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
79 {
80  MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg());
81 
82  LLVM_DEBUG(dbgs() << " Def of Mov Src:");
83  LLVM_DEBUG(DefInsn->dump());
84 
85  if (!DefInsn)
86  return false;
87 
88  if (DefInsn->isPHI()) {
89  for (unsigned i = 1, e = DefInsn->getNumOperands(); i < e; i += 2) {
90  MachineOperand &opnd = DefInsn->getOperand(i);
91 
92  if (!opnd.isReg())
93  return false;
94 
95  MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
96  // quick check on PHI incoming definitions.
97  if (!PhiDef || PhiDef->isPHI() || PhiDef->getOpcode() == BPF::COPY)
98  return false;
99  }
100  }
101 
102  if (DefInsn->getOpcode() == BPF::COPY) {
103  MachineOperand &opnd = DefInsn->getOperand(1);
104 
105  if (!opnd.isReg())
106  return false;
107 
108  unsigned Reg = opnd.getReg();
110  MRI->getRegClass(Reg) == &BPF::GPRRegClass))
111  return false;
112  }
113 
114  LLVM_DEBUG(dbgs() << " One ZExt elim sequence identified.\n");
115 
116  return true;
117 }
118 
119 bool BPFMIPeephole::eliminateZExtSeq(void) {
120  MachineInstr* ToErase = nullptr;
121  bool Eliminated = false;
122 
123  for (MachineBasicBlock &MBB : *MF) {
124  for (MachineInstr &MI : MBB) {
125  // If the previous instruction was marked for elimination, remove it now.
126  if (ToErase) {
127  ToErase->eraseFromParent();
128  ToErase = nullptr;
129  }
130 
131  // Eliminate the 32-bit to 64-bit zero extension sequence when possible.
132  //
133  // MOV_32_64 rB, wA
134  // SLL_ri rB, rB, 32
135  // SRL_ri rB, rB, 32
136  if (MI.getOpcode() == BPF::SRL_ri &&
137  MI.getOperand(2).getImm() == 32) {
138  unsigned DstReg = MI.getOperand(0).getReg();
139  unsigned ShfReg = MI.getOperand(1).getReg();
140  MachineInstr *SllMI = MRI->getVRegDef(ShfReg);
141 
142  LLVM_DEBUG(dbgs() << "Starting SRL found:");
143  LLVM_DEBUG(MI.dump());
144 
145  if (!SllMI ||
146  SllMI->isPHI() ||
147  SllMI->getOpcode() != BPF::SLL_ri ||
148  SllMI->getOperand(2).getImm() != 32)
149  continue;
150 
151  LLVM_DEBUG(dbgs() << " SLL found:");
152  LLVM_DEBUG(SllMI->dump());
153 
154  MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg());
155  if (!MovMI ||
156  MovMI->isPHI() ||
157  MovMI->getOpcode() != BPF::MOV_32_64)
158  continue;
159 
160  LLVM_DEBUG(dbgs() << " Type cast Mov found:");
161  LLVM_DEBUG(MovMI->dump());
162 
163  unsigned SubReg = MovMI->getOperand(1).getReg();
164  if (!isMovFrom32Def(MovMI)) {
165  LLVM_DEBUG(dbgs()
166  << " One ZExt elim sequence failed qualifying elim.\n");
167  continue;
168  }
169 
170  BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), DstReg)
171  .addImm(0).addReg(SubReg).addImm(BPF::sub_32);
172 
173  SllMI->eraseFromParent();
174  MovMI->eraseFromParent();
175  // MI is the right shift, we can't erase it in it's own iteration.
176  // Mark it to ToErase, and erase in the next iteration.
177  ToErase = &MI;
178  ZExtElemNum++;
179  Eliminated = true;
180  }
181  }
182  }
183 
184  return Eliminated;
185 }
186 
187 } // end default namespace
188 
189 INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE,
190  "BPF MachineSSA Peephole Optimization", false, false)
191 
192 char BPFMIPeephole::ID = 0;
193 FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }
194 
195 STATISTIC(RedundantMovElemNum, "Number of redundant moves eliminated");
196 
197 namespace {
198 
199 struct BPFMIPreEmitPeephole : public MachineFunctionPass {
200 
201  static char ID;
202  MachineFunction *MF;
203  const TargetRegisterInfo *TRI;
204 
205  BPFMIPreEmitPeephole() : MachineFunctionPass(ID) {
207  }
208 
209 private:
210  // Initialize class variables.
211  void initialize(MachineFunction &MFParm);
212 
213  bool eliminateRedundantMov(void);
214 
215 public:
216 
217  // Main entry point for this pass.
218  bool runOnMachineFunction(MachineFunction &MF) override {
219  if (skipFunction(MF.getFunction()))
220  return false;
221 
222  initialize(MF);
223 
224  return eliminateRedundantMov();
225  }
226 };
227 
228 // Initialize class variables.
230  MF = &MFParm;
231  TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
232  LLVM_DEBUG(dbgs() << "*** BPF PreEmit peephole pass ***\n\n");
233 }
234 
235 bool BPFMIPreEmitPeephole::eliminateRedundantMov(void) {
236  MachineInstr* ToErase = nullptr;
237  bool Eliminated = false;
238 
239  for (MachineBasicBlock &MBB : *MF) {
240  for (MachineInstr &MI : MBB) {
241  // If the previous instruction was marked for elimination, remove it now.
242  if (ToErase) {
243  LLVM_DEBUG(dbgs() << " Redundant Mov Eliminated:");
244  LLVM_DEBUG(ToErase->dump());
245  ToErase->eraseFromParent();
246  ToErase = nullptr;
247  }
248 
249  // Eliminate identical move:
250  //
251  // MOV rA, rA
252  //
253  // This is particularly possible to happen when sub-register support
254  // enabled. The special type cast insn MOV_32_64 involves different
255  // register class on src (i32) and dst (i64), RA could generate useless
256  // instruction due to this.
257  if (MI.getOpcode() == BPF::MOV_32_64) {
258  unsigned dst = MI.getOperand(0).getReg();
259  unsigned dst_sub = TRI->getSubReg(dst, BPF::sub_32);
260  unsigned src = MI.getOperand(1).getReg();
261 
262  if (dst_sub != src)
263  continue;
264 
265  ToErase = &MI;
266  RedundantMovElemNum++;
267  Eliminated = true;
268  }
269  }
270  }
271 
272  return Eliminated;
273 }
274 
275 } // end default namespace
276 
277 INITIALIZE_PASS(BPFMIPreEmitPeephole, "bpf-mi-pemit-peephole",
278  "BPF PreEmit Peephole Optimization", false, false)
279 
280 char BPFMIPreEmitPeephole::ID = 0;
282 {
283  return new BPFMIPreEmitPeephole();
284 }
#define DEBUG_TYPE
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
void initializeBPFMIPeepholePass(PassRegistry &)
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
FunctionPass * createBPFMIPreEmitPeepholePass()
void initializeBPFMIPreEmitPeepholePass(PassRegistry &)
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
bool isPHI() const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:412
void eraseFromParent()
Unlink &#39;this&#39; from the containing basic block and delete it.
unsigned SubReg
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
MachineInstr * getVRegDef(unsigned Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
void dump() const
Definition: Pass.cpp:130
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
unsigned getSubReg(unsigned Reg, unsigned Idx) const
Returns the physical register number of sub-register "Index" for physical register RegNo...
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
FunctionPass * createBPFMIPeepholePass()
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:34
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
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
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringRef > StandardNames)
Initialize the set of available library functions based on the specified target triple.
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 MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
IRTranslator LLVM IR MI
#define LLVM_DEBUG(X)
Definition: Debug.h:123
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:414