]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Target/BPF/BPFMIPeephole.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Target / BPF / BPFMIPeephole.cpp
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"
27 #include "llvm/CodeGen/MachineInstrBuilder.h"
28 #include "llvm/CodeGen/MachineRegisterInfo.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;
43   MachineRegisterInfo *MRI;
44
45   BPFMIPeephole() : MachineFunctionPass(ID) {
46     initializeBPFMIPeepholePass(*PassRegistry::getPassRegistry());
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.
70 void BPFMIPeephole::initialize(MachineFunction &MFParm) {
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();
108     if ((TargetRegisterInfo::isVirtualRegister(Reg) &&
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) {
205     initializeBPFMIPreEmitPeepholePass(*PassRegistry::getPassRegistry());
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.
228 void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
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;
280 FunctionPass* llvm::createBPFMIPreEmitPeepholePass()
281 {
282   return new BPFMIPreEmitPeephole();
283 }