LLVM  9.0.0svn
BPFMIPeephole.cpp
Go to the documentation of this file.
1 //===-------------- BPFMIPeephole.cpp - MI Peephole Cleanups -------------===//
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 //
9 // This pass performs peephole optimizations to cleanup ugly code sequences at
10 // MachineInstruction layer.
11 //
12 // Currently, there are two optimizations implemented:
13 // - One pre-RA MachineSSA pass to eliminate type promotion sequences, those
14 // zero extend 32-bit subregisters to 64-bit registers, if the compiler
15 // could prove the subregisters is defined by 32-bit operations in which
16 // case the upper half of the underlying 64-bit registers were zeroed
17 // implicitly.
18 //
19 // - One post-RA PreEmit pass to do final cleanup on some redundant
20 // instructions generated due to bad RA on subregister.
21 //===----------------------------------------------------------------------===//
22 
23 #include "BPF.h"
24 #include "BPFInstrInfo.h"
25 #include "BPFTargetMachine.h"
26 #include "llvm/ADT/Statistic.h"
29 
30 using namespace llvm;
31 
32 #define DEBUG_TYPE "bpf-mi-zext-elim"
33 
34 STATISTIC(ZExtElemNum, "Number of zero extension shifts eliminated");
35 
36 namespace {
37 
38 struct BPFMIPeephole : public MachineFunctionPass {
39 
40  static char ID;
41  const BPFInstrInfo *TII;
42  MachineFunction *MF;
44 
45  BPFMIPeephole() : MachineFunctionPass(ID) {
47  }
48 
49 private:
50  // Initialize class variables.
51  void initialize(MachineFunction &MFParm);
52 
53  bool isMovFrom32Def(MachineInstr *MovMI);
54  bool eliminateZExtSeq(void);
55 
56 public:
57 
58  // Main entry point for this pass.
59  bool runOnMachineFunction(MachineFunction &MF) override {
60  if (skipFunction(MF.getFunction()))
61  return false;
62 
63  initialize(MF);
64 
65  return eliminateZExtSeq();
66  }
67 };
68 
69 // Initialize class variables.
71  MF = &MFParm;
72  MRI = &MF->getRegInfo();
73  TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
74  LLVM_DEBUG(dbgs() << "*** BPF MachineSSA peephole pass ***\n\n");
75 }
76 
77 bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
78 {
79  MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg());
80 
81  LLVM_DEBUG(dbgs() << " Def of Mov Src:");
82  LLVM_DEBUG(DefInsn->dump());
83 
84  if (!DefInsn)
85  return false;
86 
87  if (DefInsn->isPHI()) {
88  for (unsigned i = 1, e = DefInsn->getNumOperands(); i < e; i += 2) {
89  MachineOperand &opnd = DefInsn->getOperand(i);
90 
91  if (!opnd.isReg())
92  return false;
93 
94  MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
95  // quick check on PHI incoming definitions.
96  if (!PhiDef || PhiDef->isPHI() || PhiDef->getOpcode() == BPF::COPY)
97  return false;
98  }
99  }
100 
101  if (DefInsn->getOpcode() == BPF::COPY) {
102  MachineOperand &opnd = DefInsn->getOperand(1);
103 
104  if (!opnd.isReg())
105  return false;
106 
107  unsigned Reg = opnd.getReg();
109  MRI->getRegClass(Reg) == &BPF::GPRRegClass))
110  return false;
111  }
112 
113  LLVM_DEBUG(dbgs() << " One ZExt elim sequence identified.\n");
114 
115  return true;
116 }
117 
118 bool BPFMIPeephole::eliminateZExtSeq(void) {
119  MachineInstr* ToErase = nullptr;
120  bool Eliminated = false;
121 
122  for (MachineBasicBlock &MBB : *MF) {
123  for (MachineInstr &MI : MBB) {
124  // If the previous instruction was marked for elimination, remove it now.
125  if (ToErase) {
126  ToErase->eraseFromParent();
127  ToErase = nullptr;
128  }
129 
130  // Eliminate the 32-bit to 64-bit zero extension sequence when possible.
131  //
132  // MOV_32_64 rB, wA
133  // SLL_ri rB, rB, 32
134  // SRL_ri rB, rB, 32
135  if (MI.getOpcode() == BPF::SRL_ri &&
136  MI.getOperand(2).getImm() == 32) {
137  unsigned DstReg = MI.getOperand(0).getReg();
138  unsigned ShfReg = MI.getOperand(1).getReg();
139  MachineInstr *SllMI = MRI->getVRegDef(ShfReg);
140 
141  LLVM_DEBUG(dbgs() << "Starting SRL found:");
142  LLVM_DEBUG(MI.dump());
143 
144  if (!SllMI ||
145  SllMI->isPHI() ||
146  SllMI->getOpcode() != BPF::SLL_ri ||
147  SllMI->getOperand(2).getImm() != 32)
148  continue;
149 
150  LLVM_DEBUG(dbgs() << " SLL found:");
151  LLVM_DEBUG(SllMI->dump());
152 
153  MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg());
154  if (!MovMI ||
155  MovMI->isPHI() ||
156  MovMI->getOpcode() != BPF::MOV_32_64)
157  continue;
158 
159  LLVM_DEBUG(dbgs() << " Type cast Mov found:");
160  LLVM_DEBUG(MovMI->dump());
161 
162  unsigned SubReg = MovMI->getOperand(1).getReg();
163  if (!isMovFrom32Def(MovMI)) {
164  LLVM_DEBUG(dbgs()
165  << " One ZExt elim sequence failed qualifying elim.\n");
166  continue;
167  }
168 
169  BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), DstReg)
170  .addImm(0).addReg(SubReg).addImm(BPF::sub_32);
171 
172  SllMI->eraseFromParent();
173  MovMI->eraseFromParent();
174  // MI is the right shift, we can't erase it in it's own iteration.
175  // Mark it to ToErase, and erase in the next iteration.
176  ToErase = &MI;
177  ZExtElemNum++;
178  Eliminated = true;
179  }
180  }
181  }
182 
183  return Eliminated;
184 }
185 
186 } // end default namespace
187 
188 INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE,
189  "BPF MachineSSA Peephole Optimization", false, false)
190 
191 char BPFMIPeephole::ID = 0;
192 FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }
193 
194 STATISTIC(RedundantMovElemNum, "Number of redundant moves eliminated");
195 
196 namespace {
197 
198 struct BPFMIPreEmitPeephole : public MachineFunctionPass {
199 
200  static char ID;
201  MachineFunction *MF;
202  const TargetRegisterInfo *TRI;
203 
204  BPFMIPreEmitPeephole() : MachineFunctionPass(ID) {
206  }
207 
208 private:
209  // Initialize class variables.
210  void initialize(MachineFunction &MFParm);
211 
212  bool eliminateRedundantMov(void);
213 
214 public:
215 
216  // Main entry point for this pass.
217  bool runOnMachineFunction(MachineFunction &MF) override {
218  if (skipFunction(MF.getFunction()))
219  return false;
220 
221  initialize(MF);
222 
223  return eliminateRedundantMov();
224  }
225 };
226 
227 // Initialize class variables.
229  MF = &MFParm;
230  TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
231  LLVM_DEBUG(dbgs() << "*** BPF PreEmit peephole pass ***\n\n");
232 }
233 
234 bool BPFMIPreEmitPeephole::eliminateRedundantMov(void) {
235  MachineInstr* ToErase = nullptr;
236  bool Eliminated = false;
237 
238  for (MachineBasicBlock &MBB : *MF) {
239  for (MachineInstr &MI : MBB) {
240  // If the previous instruction was marked for elimination, remove it now.
241  if (ToErase) {
242  LLVM_DEBUG(dbgs() << " Redundant Mov Eliminated:");
243  LLVM_DEBUG(ToErase->dump());
244  ToErase->eraseFromParent();
245  ToErase = nullptr;
246  }
247 
248  // Eliminate identical move:
249  //
250  // MOV rA, rA
251  //
252  // This is particularly possible to happen when sub-register support
253  // enabled. The special type cast insn MOV_32_64 involves different
254  // register class on src (i32) and dst (i64), RA could generate useless
255  // instruction due to this.
256  if (MI.getOpcode() == BPF::MOV_32_64) {
257  unsigned dst = MI.getOperand(0).getReg();
258  unsigned dst_sub = TRI->getSubReg(dst, BPF::sub_32);
259  unsigned src = MI.getOperand(1).getReg();
260 
261  if (dst_sub != src)
262  continue;
263 
264  ToErase = &MI;
265  RedundantMovElemNum++;
266  Eliminated = true;
267  }
268  }
269  }
270 
271  return Eliminated;
272 }
273 
274 } // end default namespace
275 
276 INITIALIZE_PASS(BPFMIPreEmitPeephole, "bpf-mi-pemit-peephole",
277  "BPF PreEmit Peephole Optimization", false, false)
278 
279 char BPFMIPreEmitPeephole::ID = 0;
281 {
282  return new BPFMIPreEmitPeephole();
283 }
#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:23
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:411
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:408
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:134
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:284
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:33
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:132
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:63
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:122
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:413