blob: 9e984d0facfbdfafb01b478315d8cb9a2d771bcb [file] [log] [blame]
Yonghong Song60fed1f2018-02-23 23:49:32 +00001//===-------------- 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//
Yonghong Songe91802f2018-03-13 06:47:06 +000013// 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.
Yonghong Song60fed1f2018-02-23 23:49:32 +000019//
Yonghong Songe91802f2018-03-13 06:47:06 +000020// - One post-RA PreEmit pass to do final cleanup on some redundant
21// instructions generated due to bad RA on subregister.
Yonghong Song60fed1f2018-02-23 23:49:32 +000022//===----------------------------------------------------------------------===//
23
24#include "BPF.h"
25#include "BPFInstrInfo.h"
26#include "BPFTargetMachine.h"
27#include "llvm/ADT/Statistic.h"
28#include "llvm/CodeGen/MachineInstrBuilder.h"
29#include "llvm/CodeGen/MachineRegisterInfo.h"
30
31using namespace llvm;
32
Yonghong Songc88bcde2018-03-13 06:47:03 +000033#define DEBUG_TYPE "bpf-mi-zext-elim"
Yonghong Song60fed1f2018-02-23 23:49:32 +000034
Yonghong Songc88bcde2018-03-13 06:47:03 +000035STATISTIC(ZExtElemNum, "Number of zero extension shifts eliminated");
Yonghong Song60fed1f2018-02-23 23:49:32 +000036
37namespace {
38
39struct BPFMIPeephole : public MachineFunctionPass {
40
41 static char ID;
42 const BPFInstrInfo *TII;
43 MachineFunction *MF;
44 MachineRegisterInfo *MRI;
45
46 BPFMIPeephole() : MachineFunctionPass(ID) {
47 initializeBPFMIPeepholePass(*PassRegistry::getPassRegistry());
48 }
49
50private:
51 // Initialize class variables.
52 void initialize(MachineFunction &MFParm);
53
Yonghong Songc88bcde2018-03-13 06:47:03 +000054 bool isMovFrom32Def(MachineInstr *MovMI);
55 bool eliminateZExtSeq(void);
Yonghong Song60fed1f2018-02-23 23:49:32 +000056
57public:
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
Yonghong Songc88bcde2018-03-13 06:47:03 +000066 return eliminateZExtSeq();
Yonghong Song60fed1f2018-02-23 23:49:32 +000067 }
68};
69
70// Initialize class variables.
71void BPFMIPeephole::initialize(MachineFunction &MFParm) {
72 MF = &MFParm;
73 MRI = &MF->getRegInfo();
74 TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
Nicola Zaghend34e60c2018-05-14 12:53:11 +000075 LLVM_DEBUG(dbgs() << "*** BPF MachineSSA peephole pass ***\n\n");
Yonghong Song60fed1f2018-02-23 23:49:32 +000076}
77
Yonghong Songc88bcde2018-03-13 06:47:03 +000078bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
79{
80 MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg());
Yonghong Song60fed1f2018-02-23 23:49:32 +000081
Nicola Zaghend34e60c2018-05-14 12:53:11 +000082 LLVM_DEBUG(dbgs() << " Def of Mov Src:");
83 LLVM_DEBUG(DefInsn->dump());
Yonghong Song82bf8bc2018-03-13 06:47:07 +000084
Yonghong Song1d28a752018-03-13 06:47:04 +000085 if (!DefInsn)
Yonghong Songc88bcde2018-03-13 06:47:03 +000086 return false;
Yonghong Song60fed1f2018-02-23 23:49:32 +000087
Yonghong Song1d28a752018-03-13 06:47:04 +000088 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
Yonghong Songc88bcde2018-03-13 06:47:03 +0000102 if (DefInsn->getOpcode() == BPF::COPY) {
103 MachineOperand &opnd = DefInsn->getOperand(1);
Yonghong Song89e47ac2018-03-13 06:47:00 +0000104
105 if (!opnd.isReg())
Yonghong Songc88bcde2018-03-13 06:47:03 +0000106 return false;
Yonghong Song89e47ac2018-03-13 06:47:00 +0000107
108 unsigned Reg = opnd.getReg();
109 if ((TargetRegisterInfo::isVirtualRegister(Reg) &&
Yonghong Songc88bcde2018-03-13 06:47:03 +0000110 MRI->getRegClass(Reg) == &BPF::GPRRegClass))
111 return false;
Yonghong Song89e47ac2018-03-13 06:47:00 +0000112 }
113
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000114 LLVM_DEBUG(dbgs() << " One ZExt elim sequence identified.\n");
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000115
Yonghong Songc88bcde2018-03-13 06:47:03 +0000116 return true;
Yonghong Song60fed1f2018-02-23 23:49:32 +0000117}
118
Yonghong Songc88bcde2018-03-13 06:47:03 +0000119bool BPFMIPeephole::eliminateZExtSeq(void) {
120 MachineInstr* ToErase = nullptr;
Yonghong Song60fed1f2018-02-23 23:49:32 +0000121 bool Eliminated = false;
Yonghong Song60fed1f2018-02-23 23:49:32 +0000122
123 for (MachineBasicBlock &MBB : *MF) {
124 for (MachineInstr &MI : MBB) {
Yonghong Songc88bcde2018-03-13 06:47:03 +0000125 // If the previous instruction was marked for elimination, remove it now.
126 if (ToErase) {
127 ToErase->eraseFromParent();
128 ToErase = nullptr;
129 }
Yonghong Song60fed1f2018-02-23 23:49:32 +0000130
Yonghong Songc88bcde2018-03-13 06:47:03 +0000131 // 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
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000142 LLVM_DEBUG(dbgs() << "Starting SRL found:");
143 LLVM_DEBUG(MI.dump());
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000144
Yonghong Songc88bcde2018-03-13 06:47:03 +0000145 if (!SllMI ||
146 SllMI->isPHI() ||
147 SllMI->getOpcode() != BPF::SLL_ri ||
148 SllMI->getOperand(2).getImm() != 32)
149 continue;
150
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000151 LLVM_DEBUG(dbgs() << " SLL found:");
152 LLVM_DEBUG(SllMI->dump());
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000153
Yonghong Songc88bcde2018-03-13 06:47:03 +0000154 MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg());
155 if (!MovMI ||
156 MovMI->isPHI() ||
157 MovMI->getOpcode() != BPF::MOV_32_64)
158 continue;
159
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000160 LLVM_DEBUG(dbgs() << " Type cast Mov found:");
161 LLVM_DEBUG(MovMI->dump());
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000162
Yonghong Song1d28a752018-03-13 06:47:04 +0000163 unsigned SubReg = MovMI->getOperand(1).getReg();
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000164 if (!isMovFrom32Def(MovMI)) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000165 LLVM_DEBUG(dbgs()
166 << " One ZExt elim sequence failed qualifying elim.\n");
Yonghong Songc88bcde2018-03-13 06:47:03 +0000167 continue;
Yonghong Song82bf8bc2018-03-13 06:47:07 +0000168 }
Yonghong Songc88bcde2018-03-13 06:47:03 +0000169
Yonghong Songc88bcde2018-03-13 06:47:03 +0000170 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;
Yonghong Song60fed1f2018-02-23 23:49:32 +0000180 }
181 }
182 }
183
184 return Eliminated;
185}
186
187} // end default namespace
188
Yonghong Songe91802f2018-03-13 06:47:06 +0000189INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE,
190 "BPF MachineSSA Peephole Optimization", false, false)
Yonghong Song60fed1f2018-02-23 23:49:32 +0000191
192char BPFMIPeephole::ID = 0;
193FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }
Yonghong Songe91802f2018-03-13 06:47:06 +0000194
195STATISTIC(RedundantMovElemNum, "Number of redundant moves eliminated");
196
197namespace {
198
199struct BPFMIPreEmitPeephole : public MachineFunctionPass {
200
201 static char ID;
202 MachineFunction *MF;
203 const TargetRegisterInfo *TRI;
204
205 BPFMIPreEmitPeephole() : MachineFunctionPass(ID) {
206 initializeBPFMIPreEmitPeepholePass(*PassRegistry::getPassRegistry());
207 }
208
209private:
210 // Initialize class variables.
211 void initialize(MachineFunction &MFParm);
212
213 bool eliminateRedundantMov(void);
214
215public:
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.
229void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
230 MF = &MFParm;
231 TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000232 LLVM_DEBUG(dbgs() << "*** BPF PreEmit peephole pass ***\n\n");
Yonghong Songe91802f2018-03-13 06:47:06 +0000233}
234
235bool 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) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000243 LLVM_DEBUG(dbgs() << " Redundant Mov Eliminated:");
244 LLVM_DEBUG(ToErase->dump());
Yonghong Songe91802f2018-03-13 06:47:06 +0000245 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
277INITIALIZE_PASS(BPFMIPreEmitPeephole, "bpf-mi-pemit-peephole",
278 "BPF PreEmit Peephole Optimization", false, false)
279
280char BPFMIPreEmitPeephole::ID = 0;
281FunctionPass* llvm::createBPFMIPreEmitPeepholePass()
282{
283 return new BPFMIPreEmitPeephole();
284}