LLVM 20.0.0git
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"
32#include "llvm/Support/Debug.h"
33#include <set>
34
35using namespace llvm;
36
37#define DEBUG_TYPE "bpf-mi-zext-elim"
38
39static cl::opt<int> GotolAbsLowBound("gotol-abs-low-bound", cl::Hidden,
40 cl::init(INT16_MAX >> 1), cl::desc("Specify gotol lower bound"));
41
42STATISTIC(ZExtElemNum, "Number of zero extension shifts eliminated");
43
44namespace {
45
46struct BPFMIPeephole : public MachineFunctionPass {
47
48 static char ID;
49 const BPFInstrInfo *TII;
52
53 BPFMIPeephole() : MachineFunctionPass(ID) {
55 }
56
57private:
58 // Initialize class variables.
59 void initialize(MachineFunction &MFParm);
60
61 bool isCopyFrom32Def(MachineInstr *CopyMI);
62 bool isInsnFrom32Def(MachineInstr *DefInsn);
63 bool isPhiFrom32Def(MachineInstr *MovMI);
64 bool isMovFrom32Def(MachineInstr *MovMI);
65 bool eliminateZExtSeq();
66 bool eliminateZExt();
67
68 std::set<MachineInstr *> PhiInsns;
69
70public:
71
72 // Main entry point for this pass.
73 bool runOnMachineFunction(MachineFunction &MF) override {
74 if (skipFunction(MF.getFunction()))
75 return false;
76
77 initialize(MF);
78
79 // First try to eliminate (zext, lshift, rshift) and then
80 // try to eliminate zext.
81 bool ZExtSeqExist, ZExtExist;
82 ZExtSeqExist = eliminateZExtSeq();
83 ZExtExist = eliminateZExt();
84 return ZExtSeqExist || ZExtExist;
85 }
86};
87
88// Initialize class variables.
89void BPFMIPeephole::initialize(MachineFunction &MFParm) {
90 MF = &MFParm;
91 MRI = &MF->getRegInfo();
92 TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
93 LLVM_DEBUG(dbgs() << "*** BPF MachineSSA ZEXT Elim peephole pass ***\n\n");
94}
95
96bool BPFMIPeephole::isCopyFrom32Def(MachineInstr *CopyMI)
97{
98 MachineOperand &opnd = CopyMI->getOperand(1);
99
100 if (!opnd.isReg())
101 return false;
102
103 // Return false if getting value from a 32bit physical register.
104 // Most likely, this physical register is aliased to
105 // function call return value or current function parameters.
106 Register Reg = opnd.getReg();
107 if (!Reg.isVirtual())
108 return false;
109
110 if (MRI->getRegClass(Reg) == &BPF::GPRRegClass)
111 return false;
112
113 MachineInstr *DefInsn = MRI->getVRegDef(Reg);
114 if (!isInsnFrom32Def(DefInsn))
115 return false;
116
117 return true;
118}
119
120bool BPFMIPeephole::isPhiFrom32Def(MachineInstr *PhiMI)
121{
122 for (unsigned i = 1, e = PhiMI->getNumOperands(); i < e; i += 2) {
123 MachineOperand &opnd = PhiMI->getOperand(i);
124
125 if (!opnd.isReg())
126 return false;
127
128 MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
129 if (!PhiDef)
130 return false;
131 if (PhiDef->isPHI()) {
132 if (!PhiInsns.insert(PhiDef).second)
133 return false;
134 if (!isPhiFrom32Def(PhiDef))
135 return false;
136 }
137 if (PhiDef->getOpcode() == BPF::COPY && !isCopyFrom32Def(PhiDef))
138 return false;
139 }
140
141 return true;
142}
143
144// The \p DefInsn instruction defines a virtual register.
145bool BPFMIPeephole::isInsnFrom32Def(MachineInstr *DefInsn)
146{
147 if (!DefInsn)
148 return false;
149
150 if (DefInsn->isPHI()) {
151 if (!PhiInsns.insert(DefInsn).second)
152 return false;
153 if (!isPhiFrom32Def(DefInsn))
154 return false;
155 } else if (DefInsn->getOpcode() == BPF::COPY) {
156 if (!isCopyFrom32Def(DefInsn))
157 return false;
158 }
159
160 return true;
161}
162
163bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
164{
165 MachineInstr *DefInsn = MRI->getVRegDef(MovMI->getOperand(1).getReg());
166
167 LLVM_DEBUG(dbgs() << " Def of Mov Src:");
168 LLVM_DEBUG(DefInsn->dump());
169
170 PhiInsns.clear();
171 if (!isInsnFrom32Def(DefInsn))
172 return false;
173
174 LLVM_DEBUG(dbgs() << " One ZExt elim sequence identified.\n");
175
176 return true;
177}
178
179bool BPFMIPeephole::eliminateZExtSeq() {
180 MachineInstr* ToErase = nullptr;
181 bool Eliminated = false;
182
183 for (MachineBasicBlock &MBB : *MF) {
184 for (MachineInstr &MI : MBB) {
185 // If the previous instruction was marked for elimination, remove it now.
186 if (ToErase) {
187 ToErase->eraseFromParent();
188 ToErase = nullptr;
189 }
190
191 // Eliminate the 32-bit to 64-bit zero extension sequence when possible.
192 //
193 // MOV_32_64 rB, wA
194 // SLL_ri rB, rB, 32
195 // SRL_ri rB, rB, 32
196 if (MI.getOpcode() == BPF::SRL_ri &&
197 MI.getOperand(2).getImm() == 32) {
198 Register DstReg = MI.getOperand(0).getReg();
199 Register ShfReg = MI.getOperand(1).getReg();
200 MachineInstr *SllMI = MRI->getVRegDef(ShfReg);
201
202 LLVM_DEBUG(dbgs() << "Starting SRL found:");
203 LLVM_DEBUG(MI.dump());
204
205 if (!SllMI ||
206 SllMI->isPHI() ||
207 SllMI->getOpcode() != BPF::SLL_ri ||
208 SllMI->getOperand(2).getImm() != 32)
209 continue;
210
211 LLVM_DEBUG(dbgs() << " SLL found:");
212 LLVM_DEBUG(SllMI->dump());
213
214 MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg());
215 if (!MovMI ||
216 MovMI->isPHI() ||
217 MovMI->getOpcode() != BPF::MOV_32_64)
218 continue;
219
220 LLVM_DEBUG(dbgs() << " Type cast Mov found:");
221 LLVM_DEBUG(MovMI->dump());
222
223 Register SubReg = MovMI->getOperand(1).getReg();
224 if (!isMovFrom32Def(MovMI)) {
226 << " One ZExt elim sequence failed qualifying elim.\n");
227 continue;
228 }
229
230 BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), DstReg)
231 .addImm(0).addReg(SubReg).addImm(BPF::sub_32);
232
233 SllMI->eraseFromParent();
234 MovMI->eraseFromParent();
235 // MI is the right shift, we can't erase it in it's own iteration.
236 // Mark it to ToErase, and erase in the next iteration.
237 ToErase = &MI;
238 ZExtElemNum++;
239 Eliminated = true;
240 }
241 }
242 }
243
244 return Eliminated;
245}
246
247bool BPFMIPeephole::eliminateZExt() {
248 MachineInstr* ToErase = nullptr;
249 bool Eliminated = false;
250
251 for (MachineBasicBlock &MBB : *MF) {
252 for (MachineInstr &MI : MBB) {
253 // If the previous instruction was marked for elimination, remove it now.
254 if (ToErase) {
255 ToErase->eraseFromParent();
256 ToErase = nullptr;
257 }
258
259 if (MI.getOpcode() != BPF::MOV_32_64)
260 continue;
261
262 // Eliminate MOV_32_64 if possible.
263 // MOV_32_64 rA, wB
264 //
265 // If wB has been zero extended, replace it with a SUBREG_TO_REG.
266 // This is to workaround BPF programs where pkt->{data, data_end}
267 // is encoded as u32, but actually the verifier populates them
268 // as 64bit pointer. The MOV_32_64 will zero out the top 32 bits.
269 LLVM_DEBUG(dbgs() << "Candidate MOV_32_64 instruction:");
270 LLVM_DEBUG(MI.dump());
271
272 if (!isMovFrom32Def(&MI))
273 continue;
274
275 LLVM_DEBUG(dbgs() << "Removing the MOV_32_64 instruction\n");
276
277 Register dst = MI.getOperand(0).getReg();
278 Register src = MI.getOperand(1).getReg();
279
280 // Build a SUBREG_TO_REG instruction.
281 BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), dst)
282 .addImm(0).addReg(src).addImm(BPF::sub_32);
283
284 ToErase = &MI;
285 Eliminated = true;
286 }
287 }
288
289 return Eliminated;
290}
291
292} // end default namespace
293
294INITIALIZE_PASS(BPFMIPeephole, DEBUG_TYPE,
295 "BPF MachineSSA Peephole Optimization For ZEXT Eliminate",
296 false, false)
297
298char BPFMIPeephole::ID = 0;
299FunctionPass* llvm::createBPFMIPeepholePass() { return new BPFMIPeephole(); }
300
301STATISTIC(RedundantMovElemNum, "Number of redundant moves eliminated");
302
303namespace {
304
305struct BPFMIPreEmitPeephole : public MachineFunctionPass {
306
307 static char ID;
308 MachineFunction *MF;
309 const TargetRegisterInfo *TRI;
310 const BPFInstrInfo *TII;
311 bool SupportGotol;
312
313 BPFMIPreEmitPeephole() : MachineFunctionPass(ID) {
315 }
316
317private:
318 // Initialize class variables.
319 void initialize(MachineFunction &MFParm);
320
321 bool in16BitRange(int Num);
322 bool eliminateRedundantMov();
323 bool adjustBranch();
324 bool insertMissingCallerSavedSpills();
325
326public:
327
328 // Main entry point for this pass.
329 bool runOnMachineFunction(MachineFunction &MF) override {
330 if (skipFunction(MF.getFunction()))
331 return false;
332
333 initialize(MF);
334
335 bool Changed;
336 Changed = eliminateRedundantMov();
337 if (SupportGotol)
338 Changed = adjustBranch() || Changed;
339 Changed |= insertMissingCallerSavedSpills();
340 return Changed;
341 }
342};
343
344// Initialize class variables.
345void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
346 MF = &MFParm;
347 TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
348 TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
349 SupportGotol = MF->getSubtarget<BPFSubtarget>().hasGotol();
350 LLVM_DEBUG(dbgs() << "*** BPF PreEmit peephole pass ***\n\n");
351}
352
353bool BPFMIPreEmitPeephole::eliminateRedundantMov() {
354 MachineInstr* ToErase = nullptr;
355 bool Eliminated = false;
356
357 for (MachineBasicBlock &MBB : *MF) {
358 for (MachineInstr &MI : MBB) {
359 // If the previous instruction was marked for elimination, remove it now.
360 if (ToErase) {
361 LLVM_DEBUG(dbgs() << " Redundant Mov Eliminated:");
362 LLVM_DEBUG(ToErase->dump());
363 ToErase->eraseFromParent();
364 ToErase = nullptr;
365 }
366
367 // Eliminate identical move:
368 //
369 // MOV rA, rA
370 //
371 // Note that we cannot remove
372 // MOV_32_64 rA, wA
373 // MOV_rr_32 wA, wA
374 // as these two instructions having side effects, zeroing out
375 // top 32 bits of rA.
376 unsigned Opcode = MI.getOpcode();
377 if (Opcode == BPF::MOV_rr) {
378 Register dst = MI.getOperand(0).getReg();
379 Register src = MI.getOperand(1).getReg();
380
381 if (dst != src)
382 continue;
383
384 ToErase = &MI;
385 RedundantMovElemNum++;
386 Eliminated = true;
387 }
388 }
389 }
390
391 return Eliminated;
392}
393
394bool BPFMIPreEmitPeephole::in16BitRange(int Num) {
395 // Well, the cut-off is not precisely at 16bit range since
396 // new codes are added during the transformation. So let us
397 // a little bit conservative.
398 return Num >= -GotolAbsLowBound && Num <= GotolAbsLowBound;
399}
400
401// Before cpu=v4, only 16bit branch target offset (-0x8000 to 0x7fff)
402// is supported for both unconditional (JMP) and condition (JEQ, JSGT,
403// etc.) branches. In certain cases, e.g., full unrolling, the branch
404// target offset might exceed 16bit range. If this happens, the llvm
405// will generate incorrect code as the offset is truncated to 16bit.
406//
407// To fix this rare case, a new insn JMPL is introduced. This new
408// insn supports supports 32bit branch target offset. The compiler
409// does not use this insn during insn selection. Rather, BPF backend
410// will estimate the branch target offset and do JMP -> JMPL and
411// JEQ -> JEQ + JMPL conversion if the estimated branch target offset
412// is beyond 16bit.
413bool BPFMIPreEmitPeephole::adjustBranch() {
414 bool Changed = false;
415 int CurrNumInsns = 0;
418 std::vector<MachineBasicBlock *> MBBs;
419
420 MachineBasicBlock *PrevBB = nullptr;
421 for (MachineBasicBlock &MBB : *MF) {
422 // MBB.size() is the number of insns in this basic block, including some
423 // debug info, e.g., DEBUG_VALUE, so we may over-count a little bit.
424 // Typically we have way more normal insns than DEBUG_VALUE insns.
425 // Also, if we indeed need to convert conditional branch like JEQ to
426 // JEQ + JMPL, we actually introduced some new insns like below.
427 CurrNumInsns += (int)MBB.size();
428 SoFarNumInsns[&MBB] = CurrNumInsns;
429 if (PrevBB != nullptr)
430 FollowThroughBB[PrevBB] = &MBB;
431 PrevBB = &MBB;
432 // A list of original BBs to make later traveral easier.
433 MBBs.push_back(&MBB);
434 }
435 FollowThroughBB[PrevBB] = nullptr;
436
437 for (unsigned i = 0; i < MBBs.size(); i++) {
438 // We have four cases here:
439 // (1). no terminator, simple follow through.
440 // (2). jmp to another bb.
441 // (3). conditional jmp to another bb or follow through.
442 // (4). conditional jmp followed by an unconditional jmp.
443 MachineInstr *CondJmp = nullptr, *UncondJmp = nullptr;
444
445 MachineBasicBlock *MBB = MBBs[i];
446 for (MachineInstr &Term : MBB->terminators()) {
447 if (Term.isConditionalBranch()) {
448 assert(CondJmp == nullptr);
449 CondJmp = &Term;
450 } else if (Term.isUnconditionalBranch()) {
451 assert(UncondJmp == nullptr);
452 UncondJmp = &Term;
453 }
454 }
455
456 // (1). no terminator, simple follow through.
457 if (!CondJmp && !UncondJmp)
458 continue;
459
460 MachineBasicBlock *CondTargetBB, *JmpBB;
461 CurrNumInsns = SoFarNumInsns[MBB];
462
463 // (2). jmp to another bb.
464 if (!CondJmp && UncondJmp) {
465 JmpBB = UncondJmp->getOperand(0).getMBB();
466 if (in16BitRange(SoFarNumInsns[JmpBB] - JmpBB->size() - CurrNumInsns))
467 continue;
468
469 // replace this insn as a JMPL.
470 BuildMI(MBB, UncondJmp->getDebugLoc(), TII->get(BPF::JMPL)).addMBB(JmpBB);
471 UncondJmp->eraseFromParent();
472 Changed = true;
473 continue;
474 }
475
476 const BasicBlock *TermBB = MBB->getBasicBlock();
477 int Dist;
478
479 // (3). conditional jmp to another bb or follow through.
480 if (!UncondJmp) {
481 CondTargetBB = CondJmp->getOperand(2).getMBB();
482 MachineBasicBlock *FollowBB = FollowThroughBB[MBB];
483 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->size() - CurrNumInsns;
484 if (in16BitRange(Dist))
485 continue;
486
487 // We have
488 // B2: ...
489 // if (cond) goto B5
490 // B3: ...
491 // where B2 -> B5 is beyond 16bit range.
492 //
493 // We do not have 32bit cond jmp insn. So we try to do
494 // the following.
495 // B2: ...
496 // if (cond) goto New_B1
497 // New_B0 goto B3
498 // New_B1: gotol B5
499 // B3: ...
500 // Basically two new basic blocks are created.
501 MachineBasicBlock *New_B0 = MF->CreateMachineBasicBlock(TermBB);
502 MachineBasicBlock *New_B1 = MF->CreateMachineBasicBlock(TermBB);
503
504 // Insert New_B0 and New_B1 into function block list.
506 MF->insert(MBB_I, New_B0);
507 MF->insert(MBB_I, New_B1);
508
509 // replace B2 cond jump
510 if (CondJmp->getOperand(1).isReg())
511 BuildMI(*MBB, MachineBasicBlock::iterator(*CondJmp), CondJmp->getDebugLoc(), TII->get(CondJmp->getOpcode()))
512 .addReg(CondJmp->getOperand(0).getReg())
513 .addReg(CondJmp->getOperand(1).getReg())
514 .addMBB(New_B1);
515 else
516 BuildMI(*MBB, MachineBasicBlock::iterator(*CondJmp), CondJmp->getDebugLoc(), TII->get(CondJmp->getOpcode()))
517 .addReg(CondJmp->getOperand(0).getReg())
518 .addImm(CondJmp->getOperand(1).getImm())
519 .addMBB(New_B1);
520
521 // it is possible that CondTargetBB and FollowBB are the same. But the
522 // above Dist checking should already filtered this case.
523 MBB->removeSuccessor(CondTargetBB);
524 MBB->removeSuccessor(FollowBB);
525 MBB->addSuccessor(New_B0);
526 MBB->addSuccessor(New_B1);
527
528 // Populate insns in New_B0 and New_B1.
529 BuildMI(New_B0, CondJmp->getDebugLoc(), TII->get(BPF::JMP)).addMBB(FollowBB);
530 BuildMI(New_B1, CondJmp->getDebugLoc(), TII->get(BPF::JMPL))
531 .addMBB(CondTargetBB);
532
533 New_B0->addSuccessor(FollowBB);
534 New_B1->addSuccessor(CondTargetBB);
535 CondJmp->eraseFromParent();
536 Changed = true;
537 continue;
538 }
539
540 // (4). conditional jmp followed by an unconditional jmp.
541 CondTargetBB = CondJmp->getOperand(2).getMBB();
542 JmpBB = UncondJmp->getOperand(0).getMBB();
543
544 // We have
545 // B2: ...
546 // if (cond) goto B5
547 // JMP B7
548 // B3: ...
549 //
550 // If only B2->B5 is out of 16bit range, we can do
551 // B2: ...
552 // if (cond) goto new_B
553 // JMP B7
554 // New_B: gotol B5
555 // B3: ...
556 //
557 // If only 'JMP B7' is out of 16bit range, we can replace
558 // 'JMP B7' with 'JMPL B7'.
559 //
560 // If both B2->B5 and 'JMP B7' is out of range, just do
561 // both the above transformations.
562 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->size() - CurrNumInsns;
563 if (!in16BitRange(Dist)) {
564 MachineBasicBlock *New_B = MF->CreateMachineBasicBlock(TermBB);
565
566 // Insert New_B0 into function block list.
567 MF->insert(++MBB->getIterator(), New_B);
568
569 // replace B2 cond jump
570 if (CondJmp->getOperand(1).isReg())
571 BuildMI(*MBB, MachineBasicBlock::iterator(*CondJmp), CondJmp->getDebugLoc(), TII->get(CondJmp->getOpcode()))
572 .addReg(CondJmp->getOperand(0).getReg())
573 .addReg(CondJmp->getOperand(1).getReg())
574 .addMBB(New_B);
575 else
576 BuildMI(*MBB, MachineBasicBlock::iterator(*CondJmp), CondJmp->getDebugLoc(), TII->get(CondJmp->getOpcode()))
577 .addReg(CondJmp->getOperand(0).getReg())
578 .addImm(CondJmp->getOperand(1).getImm())
579 .addMBB(New_B);
580
581 if (CondTargetBB != JmpBB)
582 MBB->removeSuccessor(CondTargetBB);
583 MBB->addSuccessor(New_B);
584
585 // Populate insn in New_B.
586 BuildMI(New_B, CondJmp->getDebugLoc(), TII->get(BPF::JMPL)).addMBB(CondTargetBB);
587
588 New_B->addSuccessor(CondTargetBB);
589 CondJmp->eraseFromParent();
590 Changed = true;
591 }
592
593 if (!in16BitRange(SoFarNumInsns[JmpBB] - CurrNumInsns)) {
594 BuildMI(MBB, UncondJmp->getDebugLoc(), TII->get(BPF::JMPL)).addMBB(JmpBB);
595 UncondJmp->eraseFromParent();
596 Changed = true;
597 }
598 }
599
600 return Changed;
601}
602
603static const unsigned CallerSavedRegs[] = {BPF::R0, BPF::R1, BPF::R2,
604 BPF::R3, BPF::R4, BPF::R5};
605
606struct BPFFastCall {
608 unsigned LiveCallerSavedRegs;
609};
610
611static void collectBPFFastCalls(const TargetRegisterInfo *TRI,
612 LivePhysRegs &LiveRegs, MachineBasicBlock &BB,
614 LiveRegs.init(*TRI);
615 LiveRegs.addLiveOuts(BB);
616 Calls.clear();
617 for (MachineInstr &MI : llvm::reverse(BB)) {
618 if (MI.isCall()) {
619 unsigned LiveCallerSavedRegs = 0;
620 for (MCRegister R : CallerSavedRegs) {
621 bool DoSpillFill = false;
622 for (MCPhysReg SR : TRI->subregs(R))
623 DoSpillFill |= !MI.definesRegister(SR, TRI) && LiveRegs.contains(SR);
624 if (!DoSpillFill)
625 continue;
626 LiveCallerSavedRegs |= 1 << R;
627 }
628 if (LiveCallerSavedRegs)
629 Calls.push_back({&MI, LiveCallerSavedRegs});
630 }
631 LiveRegs.stepBackward(MI);
632 }
633}
634
635static int64_t computeMinFixedObjOffset(MachineFrameInfo &MFI,
636 unsigned SlotSize) {
637 int64_t MinFixedObjOffset = 0;
638 // Same logic as in X86FrameLowering::adjustFrameForMsvcCxxEh()
639 for (int I = MFI.getObjectIndexBegin(); I < MFI.getObjectIndexEnd(); ++I) {
640 if (MFI.isDeadObjectIndex(I))
641 continue;
642 MinFixedObjOffset = std::min(MinFixedObjOffset, MFI.getObjectOffset(I));
643 }
644 MinFixedObjOffset -=
645 (SlotSize + MinFixedObjOffset % SlotSize) & (SlotSize - 1);
646 return MinFixedObjOffset;
647}
648
649bool BPFMIPreEmitPeephole::insertMissingCallerSavedSpills() {
650 MachineFrameInfo &MFI = MF->getFrameInfo();
652 LivePhysRegs LiveRegs;
653 const unsigned SlotSize = 8;
654 int64_t MinFixedObjOffset = computeMinFixedObjOffset(MFI, SlotSize);
655 bool Changed = false;
656 for (MachineBasicBlock &BB : *MF) {
657 collectBPFFastCalls(TRI, LiveRegs, BB, Calls);
658 Changed |= !Calls.empty();
659 for (BPFFastCall &Call : Calls) {
660 int64_t CurOffset = MinFixedObjOffset;
661 for (MCRegister Reg : CallerSavedRegs) {
662 if (((1 << Reg) & Call.LiveCallerSavedRegs) == 0)
663 continue;
664 // Allocate stack object
665 CurOffset -= SlotSize;
666 MFI.CreateFixedSpillStackObject(SlotSize, CurOffset);
667 // Generate spill
668 BuildMI(BB, Call.MI->getIterator(), Call.MI->getDebugLoc(),
669 TII->get(BPF::STD))
671 .addReg(BPF::R10)
672 .addImm(CurOffset);
673 // Generate fill
674 BuildMI(BB, ++Call.MI->getIterator(), Call.MI->getDebugLoc(),
675 TII->get(BPF::LDD))
677 .addReg(BPF::R10)
678 .addImm(CurOffset);
679 }
680 }
681 }
682 return Changed;
683}
684
685} // end default namespace
686
687INITIALIZE_PASS(BPFMIPreEmitPeephole, "bpf-mi-pemit-peephole",
688 "BPF PreEmit Peephole Optimization", false, false)
689
690char BPFMIPreEmitPeephole::ID = 0;
692{
693 return new BPFMIPreEmitPeephole();
694}
unsigned SubReg
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
static cl::opt< int > GotolAbsLowBound("gotol-abs-low-bound", cl::Hidden, cl::init(INT16_MAX > > 1), cl::desc("Specify gotol lower bound"))
#define DEBUG_TYPE
#define LLVM_DEBUG(...)
Definition: Debug.h:106
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:166
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringLiteral > StandardNames)
Initialize the set of available library functions based on the specified target triple.
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
bool skipFunction(const Function &F) const
Optional passes call this function to check whether the pass should be skipped.
Definition: Pass.cpp:178
A set of physical registers with utility functions to track liveness when walking backward/forward th...
Definition: LivePhysRegs.h:52
bool contains(MCPhysReg Reg) const
Returns true if register Reg is contained in the set.
Definition: LivePhysRegs.h:109
void stepBackward(const MachineInstr &MI)
Simulates liveness when stepping backwards over an instruction(bundle).
void init(const TargetRegisterInfo &TRI)
(re-)initializes and clears the set.
Definition: LivePhysRegs.h:70
void addLiveOuts(const MachineBasicBlock &MBB)
Adds all live-out registers of basic block MBB.
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
void push_back(MachineInstr *MI)
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
iterator_range< iterator > terminators()
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)
Create a spill slot at a fixed location on the stack.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
int getObjectIndexBegin() const
Return the minimum frame object index.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:575
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:578
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:499
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
bool isPHI() const
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:585
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
void dump() const
Definition: Pass.cpp:136
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
bool empty() const
Definition: SmallVector.h:81
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
self_iterator getIterator()
Definition: ilist_node.h:132
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ Define
Register definition.
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void initializeBPFMIPreEmitPeepholePass(PassRegistry &)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createBPFMIPreEmitPeepholePass()
void initializeBPFMIPeepholePass(PassRegistry &)
FunctionPass * createBPFMIPeepholePass()
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:420
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163