LLVM 24.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"
37#include "llvm/IR/Analysis.h"
38#include "llvm/Support/Debug.h"
39#include <set>
40
41using namespace llvm;
42
43#define DEBUG_TYPE "bpf-mi-zext-elim"
44
45static cl::opt<int> GotolAbsLowBound("gotol-abs-low-bound", cl::Hidden,
46 cl::init(INT16_MAX >> 1), cl::desc("Specify gotol lower bound"));
47
48STATISTIC(ZExtElemNum, "Number of zero extension shifts eliminated");
49
50namespace {
51
52struct BPFMIPeepholeImpl {
53 const BPFInstrInfo *TII;
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) {
74 initialize(MF);
75
76 // First try to eliminate (zext, lshift, rshift) and then
77 // try to eliminate zext.
78 bool ZExtSeqExist, ZExtExist;
79 ZExtSeqExist = eliminateZExtSeq();
80 ZExtExist = eliminateZExt();
81 return ZExtSeqExist || ZExtExist;
82 }
83};
84
85class BPFMIPeepholeLegacy : public MachineFunctionPass {
86public:
87 static char ID;
88 BPFMIPeepholeLegacy() : MachineFunctionPass(ID) {}
89 bool runOnMachineFunction(MachineFunction &MF) override;
90};
91
92// Initialize class variables.
93void BPFMIPeepholeImpl::initialize(MachineFunction &MFParm) {
94 MF = &MFParm;
95 MRI = &MF->getRegInfo();
96 TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
97 LLVM_DEBUG(dbgs() << "*** BPF MachineSSA ZEXT Elim peephole pass ***\n\n");
98}
99
100bool BPFMIPeepholeImpl::isCopyFrom32Def(MachineInstr *CopyMI) {
101 MachineOperand &opnd = CopyMI->getOperand(1);
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 BPFMIPeepholeImpl::isPhiFrom32Def(MachineInstr *PhiMI) {
121 for (unsigned i = 1, e = PhiMI->getNumOperands(); i < e; i += 2) {
122 MachineOperand &opnd = PhiMI->getOperand(i);
123
124 MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
125 if (!PhiDef)
126 return false;
127 if (PhiDef->isPHI()) {
128 if (!PhiInsns.insert(PhiDef).second)
129 return false;
130 if (!isPhiFrom32Def(PhiDef))
131 return false;
132 }
133 if (PhiDef->getOpcode() == BPF::COPY && !isCopyFrom32Def(PhiDef))
134 return false;
135 }
136
137 return true;
138}
139
140// The \p DefInsn instruction defines a virtual register.
141bool BPFMIPeepholeImpl::isInsnFrom32Def(MachineInstr *DefInsn) {
142 if (!DefInsn)
143 return false;
144
145 if (DefInsn->isPHI()) {
146 if (!PhiInsns.insert(DefInsn).second)
147 return false;
148 if (!isPhiFrom32Def(DefInsn))
149 return false;
150 } else if (DefInsn->getOpcode() == BPF::COPY) {
151 if (!isCopyFrom32Def(DefInsn))
152 return false;
153 }
154
155 return true;
156}
157
158bool BPFMIPeepholeImpl::isMovFrom32Def(MachineInstr *MovMI)
159{
160 const MachineOperand &Src = MovMI->getOperand(1);
161 if (Src.getSubReg())
162 return false;
163
164 MachineInstr *DefInsn = MRI->getVRegDef(Src.getReg());
165
166 LLVM_DEBUG(dbgs() << " Def of Mov Src:");
167 LLVM_DEBUG(DefInsn->dump());
168
169 PhiInsns.clear();
170 if (!isInsnFrom32Def(DefInsn))
171 return false;
172
173 LLVM_DEBUG(dbgs() << " One ZExt elim sequence identified.\n");
174
175 return true;
176}
177
178bool BPFMIPeepholeImpl::eliminateZExtSeq() {
179 MachineInstr* ToErase = nullptr;
180 bool Eliminated = false;
181
182 for (MachineBasicBlock &MBB : *MF) {
183 for (MachineInstr &MI : MBB) {
184 // If the previous instruction was marked for elimination, remove it now.
185 if (ToErase) {
186 ToErase->eraseFromParent();
187 ToErase = nullptr;
188 }
189
190 // Eliminate the 32-bit to 64-bit zero extension sequence when possible.
191 //
192 // MOV_32_64 rB, wA
193 // SLL_ri rB, rB, 32
194 // SRL_ri rB, rB, 32
195 if (MI.getOpcode() == BPF::SRL_ri &&
196 MI.getOperand(2).getImm() == 32) {
197 Register DstReg = MI.getOperand(0).getReg();
198 Register ShfReg = MI.getOperand(1).getReg();
199 MachineInstr *SllMI = MRI->getVRegDef(ShfReg);
200
201 LLVM_DEBUG(dbgs() << "Starting SRL found:");
202 LLVM_DEBUG(MI.dump());
203
204 if (!SllMI ||
205 SllMI->isPHI() ||
206 SllMI->getOpcode() != BPF::SLL_ri ||
207 SllMI->getOperand(2).getImm() != 32)
208 continue;
209
210 LLVM_DEBUG(dbgs() << " SLL found:");
211 LLVM_DEBUG(SllMI->dump());
212
213 MachineInstr *MovMI = MRI->getVRegDef(SllMI->getOperand(1).getReg());
214 if (!MovMI ||
215 MovMI->isPHI() ||
216 MovMI->getOpcode() != BPF::MOV_32_64)
217 continue;
218
219 LLVM_DEBUG(dbgs() << " Type cast Mov found:");
220 LLVM_DEBUG(MovMI->dump());
221
222 Register SubReg = MovMI->getOperand(1).getReg();
223 if (!isMovFrom32Def(MovMI)) {
225 << " One ZExt elim sequence failed qualifying elim.\n");
226 continue;
227 }
228
229 BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::SUBREG_TO_REG), DstReg)
230 .addReg(SubReg)
231 .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 BPFMIPeepholeImpl::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 .addReg(src)
283 .addImm(BPF::sub_32);
284
285 ToErase = &MI;
286 Eliminated = true;
287 }
288 }
289
290 return Eliminated;
291}
292
293} // end default namespace
294
295INITIALIZE_PASS(BPFMIPeepholeLegacy, DEBUG_TYPE,
296 "BPF MachineSSA Peephole Optimization For ZEXT Eliminate",
297 false, false)
298
299char BPFMIPeepholeLegacy::ID = 0;
300FunctionPass *llvm::createBPFMIPeepholeLegacyPass() {
301 return new BPFMIPeepholeLegacy();
302}
303
304bool BPFMIPeepholeLegacy::runOnMachineFunction(MachineFunction &MF) {
305 if (skipFunction(MF.getFunction()))
306 return false;
307
308 BPFMIPeepholeImpl Impl;
309 return Impl.runOnMachineFunction(MF);
310}
311
314 BPFMIPeepholeImpl Impl;
315 return Impl.runOnMachineFunction(MF)
319}
320
321STATISTIC(RedundantMovElemNum, "Number of redundant moves eliminated");
322
323namespace {
324
325struct BPFMIPreEmitPeepholeImpl {
326 MachineFunction *MF;
327 const TargetRegisterInfo *TRI;
328 const BPFInstrInfo *TII;
329 bool SupportGotol;
330
331private:
332 // Initialize class variables.
333 void initialize(MachineFunction &MFParm);
334
335 bool in16BitRange(int Num);
336 bool eliminateRedundantMov();
337 bool adjustBranch();
338 bool insertMissingCallerSavedSpills();
339 bool removeMayGotoZero();
340 bool addExitAfterUnreachable();
341
342public:
343
344 // Main entry point for this pass.
345 bool runOnMachineFunction(MachineFunction &MF) {
346 initialize(MF);
347 bool Changed = eliminateRedundantMov();
348 if (SupportGotol)
349 Changed |= adjustBranch();
350 Changed |= insertMissingCallerSavedSpills();
351 Changed |= removeMayGotoZero();
352 Changed |= addExitAfterUnreachable();
353 return Changed;
354 }
355};
356
357class BPFMIPreEmitPeepholeLegacy : public MachineFunctionPass {
358public:
359 static char ID;
360 BPFMIPreEmitPeepholeLegacy() : MachineFunctionPass(ID) {}
361 bool runOnMachineFunction(MachineFunction &MF) override;
362};
363
364// Initialize class variables.
365void BPFMIPreEmitPeepholeImpl::initialize(MachineFunction &MFParm) {
366 MF = &MFParm;
367 TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
368 TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
369 SupportGotol = MF->getSubtarget<BPFSubtarget>().hasGotol();
370 LLVM_DEBUG(dbgs() << "*** BPF PreEmit peephole pass ***\n\n");
371}
372
373bool BPFMIPreEmitPeepholeImpl::eliminateRedundantMov() {
374 MachineInstr* ToErase = nullptr;
375 bool Eliminated = false;
376
377 for (MachineBasicBlock &MBB : *MF) {
378 for (MachineInstr &MI : MBB) {
379 // If the previous instruction was marked for elimination, remove it now.
380 if (ToErase) {
381 LLVM_DEBUG(dbgs() << " Redundant Mov Eliminated:");
382 LLVM_DEBUG(ToErase->dump());
383 ToErase->eraseFromParent();
384 ToErase = nullptr;
385 }
386
387 // Eliminate identical move:
388 //
389 // MOV rA, rA
390 //
391 // Note that we cannot remove
392 // MOV_32_64 rA, wA
393 // MOV_rr_32 wA, wA
394 // as these two instructions having side effects, zeroing out
395 // top 32 bits of rA.
396 unsigned Opcode = MI.getOpcode();
397 if (Opcode == BPF::MOV_rr) {
398 Register dst = MI.getOperand(0).getReg();
399 Register src = MI.getOperand(1).getReg();
400
401 if (dst != src)
402 continue;
403
404 ToErase = &MI;
405 RedundantMovElemNum++;
406 Eliminated = true;
407 }
408 }
409 }
410
411 return Eliminated;
412}
413
414bool BPFMIPreEmitPeepholeImpl::in16BitRange(int Num) {
415 // Well, the cut-off is not precisely at 16bit range since
416 // new codes are added during the transformation. So let us
417 // a little bit conservative.
418 return Num >= -GotolAbsLowBound && Num <= GotolAbsLowBound;
419}
420
421// Before cpu=v4, only 16bit branch target offset (-0x8000 to 0x7fff)
422// is supported for both unconditional (JMP) and condition (JEQ, JSGT,
423// etc.) branches. In certain cases, e.g., full unrolling, the branch
424// target offset might exceed 16bit range. If this happens, the llvm
425// will generate incorrect code as the offset is truncated to 16bit.
426//
427// To fix this rare case, a new insn JMPL is introduced. This new
428// insn supports supports 32bit branch target offset. The compiler
429// does not use this insn during insn selection. Rather, BPF backend
430// will estimate the branch target offset and do JMP -> JMPL and
431// JEQ -> JEQ + JMPL conversion if the estimated branch target offset
432// is beyond 16bit.
433bool BPFMIPreEmitPeepholeImpl::adjustBranch() {
434 bool Changed = false;
435 int CurrNumInsns = 0;
436 DenseMap<MachineBasicBlock *, int> SoFarNumInsns;
437 DenseMap<MachineBasicBlock *, MachineBasicBlock *> FollowThroughBB;
438 std::vector<MachineBasicBlock *> MBBs;
439
440 MachineBasicBlock *PrevBB = nullptr;
441 for (MachineBasicBlock &MBB : *MF) {
442 // MBB.size() is the number of insns in this basic block, including some
443 // debug info, e.g., DEBUG_VALUE, so we may over-count a little bit.
444 // Typically we have way more normal insns than DEBUG_VALUE insns.
445 // Also, if we indeed need to convert conditional branch like JEQ to
446 // JEQ + JMPL, we actually introduced some new insns like below.
447 CurrNumInsns += (int)MBB.size();
448 SoFarNumInsns[&MBB] = CurrNumInsns;
449 if (PrevBB != nullptr)
450 FollowThroughBB[PrevBB] = &MBB;
451 PrevBB = &MBB;
452 // A list of original BBs to make later traveral easier.
453 MBBs.push_back(&MBB);
454 }
455 FollowThroughBB[PrevBB] = nullptr;
456
457 for (unsigned i = 0; i < MBBs.size(); i++) {
458 // We have four cases here:
459 // (1). no terminator, simple follow through.
460 // (2). jmp to another bb.
461 // (3). conditional jmp to another bb or follow through.
462 // (4). conditional jmp followed by an unconditional jmp.
463 MachineInstr *CondJmp = nullptr, *UncondJmp = nullptr;
464
465 MachineBasicBlock *MBB = MBBs[i];
466 for (MachineInstr &Term : MBB->terminators()) {
467 if (Term.isConditionalBranch()) {
468 assert(CondJmp == nullptr);
469 CondJmp = &Term;
470 } else if (Term.isUnconditionalBranch()) {
471 assert(UncondJmp == nullptr);
472 UncondJmp = &Term;
473 }
474 }
475
476 // (1). no terminator, simple follow through.
477 if (!CondJmp && !UncondJmp)
478 continue;
479
480 MachineBasicBlock *CondTargetBB, *JmpBB;
481 CurrNumInsns = SoFarNumInsns[MBB];
482
483 // (2). jmp to another bb.
484 if (!CondJmp && UncondJmp) {
485 JmpBB = UncondJmp->getOperand(0).getMBB();
486 if (in16BitRange(SoFarNumInsns[JmpBB] - JmpBB->size() - CurrNumInsns))
487 continue;
488
489 // replace this insn as a JMPL.
490 BuildMI(MBB, UncondJmp->getDebugLoc(), TII->get(BPF::JMPL)).addMBB(JmpBB);
491 UncondJmp->eraseFromParent();
492 Changed = true;
493 continue;
494 }
495
496 const BasicBlock *TermBB = MBB->getBasicBlock();
497 // 'if r1 == r2 goto' has three operands, 'unwind_goto' has one.
498 MachineOperand &CondTarget =
499 CondJmp->getOperand(CondJmp->getNumExplicitOperands() - 1);
500 int Dist;
501
502 // (3). conditional jmp to another bb or follow through.
503 if (!UncondJmp) {
504 CondTargetBB = CondTarget.getMBB();
505 MachineBasicBlock *FollowBB = FollowThroughBB[MBB];
506 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->size() - CurrNumInsns;
507 if (in16BitRange(Dist))
508 continue;
509
510 // We have
511 // B2: ...
512 // if (cond) goto B5
513 // B3: ...
514 // where B2 -> B5 is beyond 16bit range.
515 //
516 // We do not have 32bit cond jmp insn. So we try to do
517 // the following.
518 // B2: ...
519 // if (cond) goto New_B1
520 // New_B0 goto B3
521 // New_B1: gotol B5
522 // B3: ...
523 // Basically two new basic blocks are created.
524 MachineBasicBlock *New_B0 = MF->CreateMachineBasicBlock(TermBB);
525 MachineBasicBlock *New_B1 = MF->CreateMachineBasicBlock(TermBB);
526
527 // Insert New_B0 and New_B1 into function block list.
529 MF->insert(MBB_I, New_B0);
530 MF->insert(MBB_I, New_B1);
531
532 // replace B2 cond jump
533 CondTarget.setMBB(New_B1);
534
535 // it is possible that CondTargetBB and FollowBB are the same. But the
536 // above Dist checking should already filtered this case.
537 MBB->removeSuccessor(CondTargetBB);
538 MBB->removeSuccessor(FollowBB);
539 MBB->addSuccessor(New_B0);
540 MBB->addSuccessor(New_B1);
541
542 // Populate insns in New_B0 and New_B1.
543 BuildMI(New_B0, CondJmp->getDebugLoc(), TII->get(BPF::JMP)).addMBB(FollowBB);
544 BuildMI(New_B1, CondJmp->getDebugLoc(), TII->get(BPF::JMPL))
545 .addMBB(CondTargetBB);
546
547 New_B0->addSuccessor(FollowBB);
548 New_B1->addSuccessor(CondTargetBB);
549 Changed = true;
550 continue;
551 }
552
553 // (4). conditional jmp followed by an unconditional jmp.
554 CondTargetBB = CondTarget.getMBB();
555 JmpBB = UncondJmp->getOperand(0).getMBB();
556
557 // We have
558 // B2: ...
559 // if (cond) goto B5
560 // JMP B7
561 // B3: ...
562 //
563 // If only B2->B5 is out of 16bit range, we can do
564 // B2: ...
565 // if (cond) goto new_B
566 // JMP B7
567 // New_B: gotol B5
568 // B3: ...
569 //
570 // If only 'JMP B7' is out of 16bit range, we can replace
571 // 'JMP B7' with 'JMPL B7'.
572 //
573 // If both B2->B5 and 'JMP B7' is out of range, just do
574 // both the above transformations.
575 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->size() - CurrNumInsns;
576 if (!in16BitRange(Dist)) {
577 MachineBasicBlock *New_B = MF->CreateMachineBasicBlock(TermBB);
578
579 // Insert New_B0 into function block list.
580 MF->insert(++MBB->getIterator(), New_B);
581
582 // replace B2 cond jump
583 CondTarget.setMBB(New_B);
584
585 if (CondTargetBB != JmpBB)
586 MBB->removeSuccessor(CondTargetBB);
587 MBB->addSuccessor(New_B);
588
589 // Populate insn in New_B.
590 BuildMI(New_B, CondJmp->getDebugLoc(), TII->get(BPF::JMPL)).addMBB(CondTargetBB);
591
592 New_B->addSuccessor(CondTargetBB);
593 Changed = true;
594 }
595
596 if (!in16BitRange(SoFarNumInsns[JmpBB] - CurrNumInsns)) {
597 BuildMI(MBB, UncondJmp->getDebugLoc(), TII->get(BPF::JMPL)).addMBB(JmpBB);
598 UncondJmp->eraseFromParent();
599 Changed = true;
600 }
601 }
602
603 return Changed;
604}
605
606static const unsigned CallerSavedRegs[] = {BPF::R0, BPF::R1, BPF::R2,
607 BPF::R3, BPF::R4, BPF::R5};
608
609struct BPFFastCall {
610 MachineInstr *MI;
611 unsigned LiveCallerSavedRegs;
612};
613
614static void collectBPFFastCalls(const TargetRegisterInfo *TRI,
615 LivePhysRegs &LiveRegs, MachineBasicBlock &BB,
616 SmallVectorImpl<BPFFastCall> &Calls) {
617 LiveRegs.init(*TRI);
618 LiveRegs.addLiveOuts(BB);
619 Calls.clear();
620 for (MachineInstr &MI : llvm::reverse(BB)) {
621 if (MI.isCall()) {
622 unsigned LiveCallerSavedRegs = 0;
623 for (MCRegister R : CallerSavedRegs) {
624 bool DoSpillFill = false;
625 for (MCPhysReg SR : TRI->subregs(R))
626 DoSpillFill |= !MI.definesRegister(SR, TRI) && LiveRegs.contains(SR);
627 if (!DoSpillFill)
628 continue;
629 LiveCallerSavedRegs |= 1 << R;
630 }
631 if (LiveCallerSavedRegs)
632 Calls.push_back({&MI, LiveCallerSavedRegs});
633 }
634 LiveRegs.stepBackward(MI);
635 }
636}
637
638static int64_t computeMinFixedObjOffset(MachineFrameInfo &MFI,
639 unsigned SlotSize) {
640 int64_t MinFixedObjOffset = 0;
641 // Same logic as in X86FrameLowering::adjustFrameForMsvcCxxEh()
642 for (int I = MFI.getObjectIndexBegin(); I < MFI.getObjectIndexEnd(); ++I) {
643 if (MFI.isDeadObjectIndex(I))
644 continue;
645 MinFixedObjOffset = std::min(MinFixedObjOffset, MFI.getObjectOffset(I));
646 }
647 MinFixedObjOffset -=
648 (SlotSize + MinFixedObjOffset % SlotSize) & (SlotSize - 1);
649 return MinFixedObjOffset;
650}
651
652bool BPFMIPreEmitPeepholeImpl::insertMissingCallerSavedSpills() {
653 MachineFrameInfo &MFI = MF->getFrameInfo();
655 LivePhysRegs LiveRegs;
656 const unsigned SlotSize = 8;
657 int64_t MinFixedObjOffset = computeMinFixedObjOffset(MFI, SlotSize);
658 bool Changed = false;
659 for (MachineBasicBlock &BB : *MF) {
660 collectBPFFastCalls(TRI, LiveRegs, BB, Calls);
661 Changed |= !Calls.empty();
662 for (BPFFastCall &Call : Calls) {
663 int64_t CurOffset = MinFixedObjOffset;
664 for (MCRegister Reg : CallerSavedRegs) {
665 if (((1 << Reg) & Call.LiveCallerSavedRegs) == 0)
666 continue;
667 // Allocate stack object
668 CurOffset -= SlotSize;
669 MFI.CreateFixedSpillStackObject(SlotSize, CurOffset);
670 // Generate spill
671 BuildMI(BB, Call.MI->getIterator(), Call.MI->getDebugLoc(),
672 TII->get(BPF::STD))
673 .addReg(Reg, RegState::Kill)
674 .addReg(BPF::R10)
675 .addImm(CurOffset);
676 // Generate fill
677 BuildMI(BB, ++Call.MI->getIterator(), Call.MI->getDebugLoc(),
678 TII->get(BPF::LDD))
679 .addReg(Reg, RegState::Define)
680 .addReg(BPF::R10)
681 .addImm(CurOffset);
682 }
683 }
684 }
685 return Changed;
686}
687
688bool BPFMIPreEmitPeepholeImpl::removeMayGotoZero() {
689 bool Changed = false;
690 MachineBasicBlock *Prev_MBB, *Curr_MBB = nullptr;
691
692 for (MachineBasicBlock &MBB : make_early_inc_range(reverse(*MF))) {
693 Prev_MBB = Curr_MBB;
694 Curr_MBB = &MBB;
695 if (Prev_MBB == nullptr || Curr_MBB->empty())
696 continue;
697
698 MachineInstr &MI = Curr_MBB->back();
699 if (MI.getOpcode() != TargetOpcode::INLINEASM_BR)
700 continue;
701
702 const char *AsmStr = MI.getOperand(0).getSymbolName();
704 SplitString(AsmStr, AsmPieces, ";\n");
705
706 // Do not support multiple insns in one inline asm.
707 if (AsmPieces.size() != 1)
708 continue;
709
710 // The asm insn must be a may_goto insn.
711 SmallVector<StringRef, 4> AsmOpPieces;
712 SplitString(AsmPieces[0], AsmOpPieces, " ");
713 if (AsmOpPieces.size() != 2 || AsmOpPieces[0] != "may_goto")
714 continue;
715 // Enforce the format of 'may_goto <label>'.
716 if (AsmOpPieces[1] != "${0:l}" && AsmOpPieces[1] != "$0")
717 continue;
718
719 // Get the may_goto branch target.
720 MachineOperand &MO = MI.getOperand(InlineAsm::MIOp_FirstOperand + 1);
721 if (!MO.isMBB() || MO.getMBB() != Prev_MBB)
722 continue;
723
724 Changed = true;
725 if (Curr_MBB->begin() == MI) {
726 // Single 'may_goto' insn in the same basic block.
727 Curr_MBB->removeSuccessor(Prev_MBB);
728 for (MachineBasicBlock *Pred : Curr_MBB->predecessors())
729 Pred->replaceSuccessor(Curr_MBB, Prev_MBB);
730 Curr_MBB->eraseFromParent();
731 Curr_MBB = Prev_MBB;
732 } else {
733 // Remove 'may_goto' insn.
734 MI.eraseFromParent();
735 }
736 }
737
738 return Changed;
739}
740
741// If the last non-debug insn in a function is 'JAL &bpf_unreachable', let us
742// add an 'exit' insn after it. This will ensure no fallthrough at the last
743// insn, making kernel verification easier.
744bool BPFMIPreEmitPeepholeImpl::addExitAfterUnreachable() {
745 MachineBasicBlock &MBB = MF->back();
746 auto MBBI = MBB.getLastNonDebugInstr(/*SkipPseudoOp=*/false);
747 if (MBBI == MBB.end() || MBBI->getOpcode() != BPF::JAL ||
748 !MBBI->getOperand(0).isGlobal() ||
749 MBBI->getOperand(0).getGlobal()->getName() != BPF_TRAP)
750 return false;
751
752 BuildMI(&MBB, MBBI->getDebugLoc(), TII->get(BPF::RET));
753 return true;
754}
755
756} // namespace
757
758INITIALIZE_PASS(BPFMIPreEmitPeepholeLegacy, "bpf-mi-pre-emit-peephole",
759 "BPF PreEmit Peephole Optimization", false, false)
760
761char BPFMIPreEmitPeepholeLegacy::ID = 0;
762FunctionPass *llvm::createBPFMIPreEmitPeepholeLegacyPass() {
763 return new BPFMIPreEmitPeepholeLegacy();
764}
765
766bool BPFMIPreEmitPeepholeLegacy::runOnMachineFunction(MachineFunction &MF) {
767 if (skipFunction(MF.getFunction()))
768 return false;
769 BPFMIPreEmitPeepholeImpl Impl;
770 return Impl.runOnMachineFunction(MF);
771}
772
773PreservedAnalyses
776 BPFMIPreEmitPeepholeImpl Impl;
777 return Impl.runOnMachineFunction(MF)
781}
782
783namespace {
784
785bool expandStackArgPseudos(MachineFunction &MF) {
786 bool Changed = false;
787 const BPFInstrInfo *TII = MF.getSubtarget<BPFSubtarget>().getInstrInfo();
788 for (MachineBasicBlock &MBB : MF) {
789 for (auto It = MBB.begin(), End = MBB.end(); It != End;) {
790 MachineInstr &MI = *It++;
791 DebugLoc DL = MI.getDebugLoc();
792
793 switch (MI.getOpcode()) {
794 default:
795 break;
796
797 case BPF::LOAD_STACK_ARG_PSEUDO: {
798 Register DstReg = MI.getOperand(0).getReg();
799 int16_t Off = MI.getOperand(1).getImm();
800
801 BuildMI(MBB, MI, DL, TII->get(BPF::LDD), DstReg)
802 .addReg(BPF::R11)
803 .addImm(Off);
804 MI.eraseFromParent();
805 Changed = true;
806 break;
807 }
808
809 case BPF::STORE_STACK_ARG_PSEUDO: {
810 int16_t Off = MI.getOperand(0).getImm();
811 const MachineOperand &SrcMO = MI.getOperand(1);
812 Register SrcReg = SrcMO.getReg();
813 bool IsKill = SrcMO.isKill();
814
815 BuildMI(MBB, MI, DL, TII->get(BPF::STD))
816 .addReg(SrcReg, getKillRegState(IsKill))
817 .addReg(BPF::R11)
818 .addImm(Off);
819 MI.eraseFromParent();
820 Changed = true;
821 break;
822 }
823
824 case BPF::STORE_STACK_ARG_IMM_PSEUDO: {
825 int16_t Off = MI.getOperand(0).getImm();
826 int32_t Val = MI.getOperand(1).getImm();
827
828 BuildMI(MBB, MI, DL, TII->get(BPF::STD_imm))
829 .addImm(Val)
830 .addReg(BPF::R11)
831 .addImm(Off);
832 MI.eraseFromParent();
833 Changed = true;
834 break;
835 }
836 }
837 }
838 }
839
840 return Changed;
841}
842
843class BPFMIExpandStackArgPseudosLegacy : public MachineFunctionPass {
844public:
845 static char ID;
846 BPFMIExpandStackArgPseudosLegacy() : MachineFunctionPass(ID) {}
847 bool runOnMachineFunction(MachineFunction &MF) override;
848};
849
850} // namespace
851
852INITIALIZE_PASS(BPFMIExpandStackArgPseudosLegacy,
853 "bpf-mi-expand-stack-arg-pseudos",
854 "BPF Stack argument psuedo expansion", false, false)
855
856char BPFMIExpandStackArgPseudosLegacy::ID = 0;
857FunctionPass *llvm::createBPFMIExpandStackArgPseudosLegacyPass() {
858 return new BPFMIExpandStackArgPseudosLegacy();
859}
860
861bool BPFMIExpandStackArgPseudosLegacy::runOnMachineFunction(
862 MachineFunction &MF) {
863 return expandStackArgPseudos(MF);
864}
865
866PreservedAnalyses
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static cl::opt< int > GotolAbsLowBound("gotol-abs-low-bound", cl::Hidden, cl::init(INT16_MAX > > 1), cl::desc("Specify gotol lower bound"))
#define BPF_TRAP
Definition BPF.h:29
#define DEBUG_TYPE
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:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
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:171
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
A debug info location.
Definition DebugLoc.h:126
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
LLVM_ABI iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
iterator_range< iterator > terminators()
iterator_range< pred_iterator > predecessors()
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
LLVM_ABI 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...
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.
BasicBlockListType::iterator iterator
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
MachineBasicBlock * getMBB() const
void setMBB(MachineBasicBlock *MBB)
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
void push_back(const T &Elt)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
self_iterator getIterator()
Definition ilist_node.h:123
CallInst * Call
Changed
Pass manager infrastructure for declaring and invalidating analyses.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr RegState getKillRegState(bool B)
FunctionPass * createBPFMIPeepholeLegacyPass()
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:649
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI void SplitString(StringRef Source, SmallVectorImpl< StringRef > &OutFragments, StringRef Delimiters=" \t\n\v\f\r")
SplitString - Split up the specified string according to the specified delimiters,...
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
FunctionPass * createBPFMIPreEmitPeepholeLegacyPass()
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:267
FunctionPass * createBPFMIExpandStackArgPseudosLegacyPass()