blob: 156ba793e35921b50b3c9eabea11cdd3f26ae849 [file] [log] [blame]
Yonghong Song60fed1f2018-02-23 23:49:32 +00001//===-------------- BPFMIPeephole.cpp - MI Peephole Cleanups -------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Yonghong Song60fed1f2018-02-23 23:49:32 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This pass performs peephole optimizations to cleanup ugly code sequences at
10// MachineInstruction layer.
11//
Yonghong Songe91802f2018-03-13 06:47:06 +000012// 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.
Yonghong Song60fed1f2018-02-23 23:49:32 +000018//
Yonghong Songe91802f2018-03-13 06:47:06 +000019// - One post-RA PreEmit pass to do final cleanup on some redundant
20// instructions generated due to bad RA on subregister.
Yonghong Song60fed1f2018-02-23 23:49:32 +000021//===----------------------------------------------------------------------===//
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
30using namespace llvm;
31
Yonghong Songc88bcde2018-03-13 06:47:03 +000032#define DEBUG_TYPE "bpf-mi-zext-elim"
Yonghong Song60fed1f2018-02-23 23:49:32 +000033
Yonghong Songc88bcde2018-03-13 06:47:03 +000034STATISTIC(ZExtElemNum, "Number of zero extension shifts eliminated");
Yonghong Song60fed1f2018-02-23 23:49:32 +000035
36namespace {
37
38struct 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
49private:
50 // Initialize class variables.
51 void initialize(MachineFunction &MFParm);
52
Yonghong Songc88bcde2018-03-13 06:47:03 +000053 bool isMovFrom32Def(MachineInstr *MovMI);
54 bool eliminateZExtSeq(void);
Yonghong Song60fed1f2018-02-23 23:49:32 +000055
56public:
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
Yonghong Songc88bcde2018-03-13 06:47:03 +000065 return eliminateZExtSeq();
Yonghong Song60fed1f2018-02-23 23:49:32 +000066 }
67};
68
69// Initialize class variables.
70void BPFMIPeephole::initialize(MachineFunction &MFParm) {
71 MF = &MFParm;
72 MRI = &MF->getRegInfo();
73 TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
Nicola Zaghend34e60c2018-05-14 12:53:11 +000074 LLVM_DEBUG(dbgs() << "*** BPF MachineSSA peephole pass ***\n\n");
Yonghong Song60fed1f2018-02-23 23:49:32 +000075}
76
Yonghong Songc88bcde2018-03-13 06:47:03 +000077bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
78{
79 MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg());
Yonghong Song60fed1f2018-02-23 23:49:32 +000080
Nicola Zaghend34e60c2018-05-14 12:53:11 +000081 LLVM_DEBUG(dbgs() << " Def of Mov Src:");
82 LLVM_DEBUG(DefInsn->dump());
Yonghong Song82bf8bc2018-03-13 06:47:07 +000083
Yonghong Song1d28a752018-03-13 06:47:04 +000084 if (!DefInsn)
Yonghong Songc88bcde2018-03-13 06:47:03 +000085 return false;
Yonghong Song60fed1f2018-02-23 23:49:32 +000086
Yonghong Song1d28a752018-03-13 06:47:04 +000087 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
Yonghong Songc88bcde2018-03-13 06:47:03 +0000101 if (DefInsn->getOpcode() == BPF::COPY) {
102 MachineOperand &opnd = DefInsn->getOperand(1);
Yonghong Song89e47ac2018-03-13 06:47:00 +0000103
104 if (!opnd.isReg())
Yonghong Songc88bcde2018-03-13 06:47:03 +0000105 return false;
Yonghong Song89e47ac2018-03-13 06:47:00 +0000106
107 unsigned Reg = opnd.getReg();
108 if ((TargetRegisterInfo::isVirtualRegister(Reg) &&
Yonghong Songc88bcde2018-03-13 06:47:03 +0000109 MRI->getRegClass(Reg) == &BPF::GPRRegClass))
110 return false;
Yonghong Song89e47ac2018-03-13 06:47:00 +0000111 }
112
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000113 LLVM_DEBUG(dbgs() << " One ZExt elim sequence identified.\n");
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000114
Yonghong Songc88bcde2018-03-13 06:47:03 +0000115 return true;
Yonghong Song60fed1f2018-02-23 23:49:32 +0000116}
117
Yonghong Songc88bcde2018-03-13 06:47:03 +0000118bool BPFMIPeephole::eliminateZExtSeq(void) {
119 MachineInstr* ToErase = nullptr;
Yonghong Song60fed1f2018-02-23 23:49:32 +0000120 bool Eliminated = false;
Yonghong Song60fed1f2018-02-23 23:49:32 +0000121
122 for (MachineBasicBlock &MBB : *MF) {
123 for (MachineInstr &MI : MBB) {
Yonghong Songc88bcde2018-03-13 06:47:03 +0000124 // If the previous instruction was marked for elimination, remove it now.
125 if (ToErase) {
126 ToErase->eraseFromParent();
127 ToErase = nullptr;
128 }
Yonghong Song60fed1f2018-02-23 23:49:32 +0000129
Yonghong Songc88bcde2018-03-13 06:47:03 +0000130 // 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
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000141 LLVM_DEBUG(dbgs() << "Starting SRL found:");
142 LLVM_DEBUG(MI.dump());
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000143
Yonghong Songc88bcde2018-03-13 06:47:03 +0000144 if (!SllMI ||
145 SllMI->isPHI() ||
146 SllMI->getOpcode() != BPF::SLL_ri ||
147 SllMI->getOperand(2).getImm() != 32)
148 continue;
149
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000150 LLVM_DEBUG(dbgs() << " SLL found:");
151 LLVM_DEBUG(SllMI->dump());
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000152
Yonghong Songc88bcde2018-03-13 06:47:03 +0000153 MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg());
154 if (!MovMI ||
155 MovMI->isPHI() ||
156 MovMI->getOpcode() != BPF::MOV_32_64)
157 continue;
158
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000159 LLVM_DEBUG(dbgs() << " Type cast Mov found:");
160 LLVM_DEBUG(MovMI->dump());
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000161
Yonghong Song1d28a752018-03-13 06:47:04 +0000162 unsigned SubReg = MovMI->getOperand(1).getReg();
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000163 if (!isMovFrom32Def(MovMI)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000164 LLVM_DEBUG(dbgs()
165 << " One ZExt elim sequence failed qualifying elim.\n");
Yonghong Songc88bcde2018-03-13 06:47:03 +0000166 continue;
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000167 }
Yonghong Songc88bcde2018-03-13 06:47:03 +0000168
Yonghong Songc88bcde2018-03-13 06:47:03 +0000169 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;
Yonghong Song60fed1f2018-02-23 23:49:32 +0000179 }
180 }
181 }
182
183 return Eliminated;
184}
185
186} // end default namespace
187
Yonghong Songe91802f2018-03-13 06:47:06 +0000188INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE,
189 "BPF MachineSSA Peephole Optimization", false, false)
Yonghong Song60fed1f2018-02-23 23:49:32 +0000190
191char BPFMIPeephole::ID = 0;
192FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }
Yonghong Songe91802f2018-03-13 06:47:06 +0000193
194STATISTIC(RedundantMovElemNum, "Number of redundant moves eliminated");
195
196namespace {
197
198struct 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
208private:
209 // Initialize class variables.
210 void initialize(MachineFunction &MFParm);
211
212 bool eliminateRedundantMov(void);
213
214public:
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.
228void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
229 MF = &MFParm;
230 TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000231 LLVM_DEBUG(dbgs() << "*** BPF PreEmit peephole pass ***\n\n");
Yonghong Songe91802f2018-03-13 06:47:06 +0000232}
233
234bool 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) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000242 LLVM_DEBUG(dbgs() << " Redundant Mov Eliminated:");
243 LLVM_DEBUG(ToErase->dump());
Yonghong Songe91802f2018-03-13 06:47:06 +0000244 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
276INITIALIZE_PASS(BPFMIPreEmitPeephole, "bpf-mi-pemit-peephole",
277 "BPF PreEmit Peephole Optimization", false, false)
278
279char BPFMIPreEmitPeephole::ID = 0;
280FunctionPass* llvm::createBPFMIPreEmitPeepholePass()
281{
282 return new BPFMIPreEmitPeephole();
283}