LLVM 22.0.0git
MipsDelaySlotFiller.cpp
Go to the documentation of this file.
1//===- MipsDelaySlotFiller.cpp - Mips Delay Slot Filler -------------------===//
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// Simple pass to fill delay slots with useful instructions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Mips.h"
14#include "MipsInstrInfo.h"
15#include "MipsSubtarget.h"
16#include "llvm/ADT/BitVector.h"
17#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/Statistic.h"
22#include "llvm/ADT/StringRef.h"
36#include "llvm/MC/MCInstrDesc.h"
43#include <cassert>
44#include <iterator>
45#include <memory>
46#include <utility>
47
48using namespace llvm;
49
50#define DEBUG_TYPE "mips-delay-slot-filler"
51
52STATISTIC(FilledSlots, "Number of delay slots filled");
53STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that"
54 " are not NOP.");
55
57 "disable-mips-delay-filler",
58 cl::init(false),
59 cl::desc("Fill all delay slots with NOPs."),
61
63 "disable-mips-df-forward-search",
64 cl::init(true),
65 cl::desc("Disallow MIPS delay filler to search forward."),
67
69 "disable-mips-df-succbb-search",
70 cl::init(true),
71 cl::desc("Disallow MIPS delay filler to search successor basic blocks."),
73
75 "disable-mips-df-backward-search",
76 cl::init(false),
77 cl::desc("Disallow MIPS delay filler to search backward."),
79
81
82namespace {
83
84 using Iter = MachineBasicBlock::iterator;
85 using ReverseIter = MachineBasicBlock::reverse_iterator;
87
88 class RegDefsUses {
89 public:
90 RegDefsUses(const TargetRegisterInfo &TRI);
91
92 void init(const MachineInstr &MI);
93
94 /// This function sets all caller-saved registers in Defs.
95 void setCallerSaved(const MachineInstr &MI);
96
97 /// This function sets all unallocatable registers in Defs.
98 void setUnallocatableRegs(const MachineFunction &MF);
99
100 /// Set bits in Uses corresponding to MBB's live-out registers except for
101 /// the registers that are live-in to SuccBB.
102 void addLiveOut(const MachineBasicBlock &MBB,
103 const MachineBasicBlock &SuccBB);
104
105 bool update(const MachineInstr &MI, unsigned Begin, unsigned End);
106
107 private:
108 bool checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses, unsigned Reg,
109 bool IsDef) const;
110
111 /// Returns true if Reg or its alias is in RegSet.
112 bool isRegInSet(const BitVector &RegSet, unsigned Reg) const;
113
114 const TargetRegisterInfo &TRI;
115 BitVector Defs, Uses;
116 };
117
118 /// Base class for inspecting loads and stores.
119 class InspectMemInstr {
120 public:
121 InspectMemInstr(bool ForbidMemInstr_) : ForbidMemInstr(ForbidMemInstr_) {}
122 virtual ~InspectMemInstr() = default;
123
124 /// Return true if MI cannot be moved to delay slot.
125 bool hasHazard(const MachineInstr &MI);
126
127 protected:
128 /// Flags indicating whether loads or stores have been seen.
129 bool OrigSeenLoad = false;
130 bool OrigSeenStore = false;
131 bool SeenLoad = false;
132 bool SeenStore = false;
133
134 /// Memory instructions are not allowed to move to delay slot if this flag
135 /// is true.
136 bool ForbidMemInstr;
137
138 private:
139 virtual bool hasHazard_(const MachineInstr &MI) = 0;
140 };
141
142 /// This subclass rejects any memory instructions.
143 class NoMemInstr : public InspectMemInstr {
144 public:
145 NoMemInstr() : InspectMemInstr(true) {}
146
147 private:
148 bool hasHazard_(const MachineInstr &MI) override { return true; }
149 };
150
151 /// This subclass accepts loads from stacks and constant loads.
152 class LoadFromStackOrConst : public InspectMemInstr {
153 public:
154 LoadFromStackOrConst() : InspectMemInstr(false) {}
155
156 private:
157 bool hasHazard_(const MachineInstr &MI) override;
158 };
159
160 /// This subclass uses memory dependence information to determine whether a
161 /// memory instruction can be moved to a delay slot.
162 class MemDefsUses : public InspectMemInstr {
163 public:
164 explicit MemDefsUses(const MachineFrameInfo *MFI);
165
166 private:
167 using ValueType = PointerUnion<const Value *, const PseudoSourceValue *>;
168
169 bool hasHazard_(const MachineInstr &MI) override;
170
171 /// Update Defs and Uses. Return true if there exist dependences that
172 /// disqualify the delay slot candidate between V and values in Uses and
173 /// Defs.
174 bool updateDefsUses(ValueType V, bool MayStore);
175
176 /// Get the list of underlying objects of MI's memory operand.
177 bool getUnderlyingObjects(const MachineInstr &MI,
178 SmallVectorImpl<ValueType> &Objects) const;
179
180 const MachineFrameInfo *MFI;
181 SmallPtrSet<ValueType, 4> Uses, Defs;
182
183 /// Flags indicating whether loads or stores with no underlying objects have
184 /// been seen.
185 bool SeenNoObjLoad = false;
186 bool SeenNoObjStore = false;
187 };
188
189 class MipsDelaySlotFiller : public MachineFunctionPass {
190 public:
191 MipsDelaySlotFiller() : MachineFunctionPass(ID) {}
192
193 StringRef getPassName() const override { return "Mips Delay Slot Filler"; }
194
195 bool runOnMachineFunction(MachineFunction &F) override {
196 TM = &F.getTarget();
197 bool Changed = false;
198 for (MachineBasicBlock &MBB : F)
199 Changed |= runOnMachineBasicBlock(MBB);
200
201 // This pass invalidates liveness information when it reorders
202 // instructions to fill delay slot. Without this, -verify-machineinstrs
203 // will fail.
204 if (Changed)
205 F.getRegInfo().invalidateLiveness();
206
207 return Changed;
208 }
209
210 MachineFunctionProperties getRequiredProperties() const override {
211 return MachineFunctionProperties().setNoVRegs();
212 }
213
214 void getAnalysisUsage(AnalysisUsage &AU) const override {
215 AU.addRequired<MachineBranchProbabilityInfoWrapperPass>();
217 }
218
219 static char ID;
220
221 private:
222 bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
223
224 Iter replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch,
225 const DebugLoc &DL);
226
227 /// This function checks if it is valid to move Candidate to the delay slot
228 /// and returns true if it isn't. It also updates memory and register
229 /// dependence information.
230 bool delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU,
231 InspectMemInstr &IM) const;
232
233 /// This function searches range [Begin, End) for an instruction that can be
234 /// moved to the delay slot. Returns true on success.
235 template<typename IterTy>
236 bool searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End,
237 RegDefsUses &RegDU, InspectMemInstr &IM, Iter Slot,
238 IterTy &Filler) const;
239
240 /// This function searches in the backward direction for an instruction that
241 /// can be moved to the delay slot. Returns true on success.
242 bool searchBackward(MachineBasicBlock &MBB, MachineInstr &Slot) const;
243
244 /// This function searches MBB in the forward direction for an instruction
245 /// that can be moved to the delay slot. Returns true on success.
246 bool searchForward(MachineBasicBlock &MBB, Iter Slot) const;
247
248 /// This function searches one of MBB's successor blocks for an instruction
249 /// that can be moved to the delay slot and inserts clones of the
250 /// instruction into the successor's predecessor blocks.
251 bool searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const;
252
253 /// Pick a successor block of MBB. Return NULL if MBB doesn't have a
254 /// successor block that is not a landing pad.
255 MachineBasicBlock *selectSuccBB(MachineBasicBlock &B) const;
256
257 /// This function analyzes MBB and returns an instruction with an unoccupied
258 /// slot that branches to Dst.
259 std::pair<MipsInstrInfo::BranchType, MachineInstr *>
260 getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const;
261
262 /// Examine Pred and see if it is possible to insert an instruction into
263 /// one of its branches delay slot or its end.
264 bool examinePred(MachineBasicBlock &Pred, const MachineBasicBlock &Succ,
265 RegDefsUses &RegDU, bool &HasMultipleSuccs,
266 BB2BrMap &BrMap) const;
267
268 bool terminateSearch(const MachineInstr &Candidate) const;
269
270 const TargetMachine *TM = nullptr;
271 };
272
273} // end anonymous namespace
274
275char MipsDelaySlotFiller::ID = 0;
276
277static bool hasUnoccupiedSlot(const MachineInstr *MI) {
278 return MI->hasDelaySlot() && !MI->isBundledWithSucc();
279}
280
281INITIALIZE_PASS(MipsDelaySlotFiller, DEBUG_TYPE,
282 "Fill delay slot for MIPS", false, false)
283
284/// This function inserts clones of Filler into predecessor blocks.
285static void insertDelayFiller(Iter Filler, const BB2BrMap &BrMap) {
286 MachineFunction *MF = Filler->getParent()->getParent();
287
288 for (const auto &I : BrMap) {
289 if (I.second) {
290 MIBundleBuilder(I.second).append(MF->CloneMachineInstr(&*Filler));
291 ++UsefulSlots;
292 } else {
293 I.first->push_back(MF->CloneMachineInstr(&*Filler));
294 }
295 }
296}
297
298/// This function adds registers Filler defines to MBB's live-in register list.
299static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) {
300 for (const MachineOperand &MO : Filler->operands()) {
301 unsigned R;
302
303 if (!MO.isReg() || !MO.isDef() || !(R = MO.getReg()))
304 continue;
305
306#ifndef NDEBUG
307 const MachineFunction &MF = *MBB.getParent();
309 "Shouldn't move an instruction with unallocatable registers across "
310 "basic block boundaries.");
311#endif
312
313 if (!MBB.isLiveIn(R))
314 MBB.addLiveIn(R);
315 }
316}
317
318RegDefsUses::RegDefsUses(const TargetRegisterInfo &TRI)
319 : TRI(TRI), Defs(TRI.getNumRegs(), false), Uses(TRI.getNumRegs(), false) {}
320
321void RegDefsUses::init(const MachineInstr &MI) {
322 // Add all register operands which are explicit and non-variadic.
323 update(MI, 0, MI.getDesc().getNumOperands());
324
325 // If MI is a call, add RA to Defs to prevent users of RA from going into
326 // delay slot.
327 if (MI.isCall())
328 Defs.set(Mips::RA);
329
330 // Add all implicit register operands of branch instructions except
331 // register AT.
332 if (MI.isBranch()) {
333 update(MI, MI.getDesc().getNumOperands(), MI.getNumOperands());
334 Defs.reset(Mips::AT);
335 }
336}
337
338void RegDefsUses::setCallerSaved(const MachineInstr &MI) {
339 assert(MI.isCall());
340
341 // Add RA/RA_64 to Defs to prevent users of RA/RA_64 from going into
342 // the delay slot. The reason is that RA/RA_64 must not be changed
343 // in the delay slot so that the callee can return to the caller.
344 if (MI.definesRegister(Mips::RA, /*TRI=*/nullptr) ||
345 MI.definesRegister(Mips::RA_64, /*TRI=*/nullptr)) {
346 Defs.set(Mips::RA);
347 Defs.set(Mips::RA_64);
348 }
349
350 // If MI is a call, add all caller-saved registers to Defs.
351 BitVector CallerSavedRegs(TRI.getNumRegs(), true);
352
353 CallerSavedRegs.reset(Mips::ZERO);
354 CallerSavedRegs.reset(Mips::ZERO_64);
355
356 for (const MCPhysReg *R = TRI.getCalleeSavedRegs(MI.getParent()->getParent());
357 *R; ++R)
358 for (MCRegAliasIterator AI(*R, &TRI, true); AI.isValid(); ++AI)
359 CallerSavedRegs.reset(*AI);
360
361 Defs |= CallerSavedRegs;
362}
363
364void RegDefsUses::setUnallocatableRegs(const MachineFunction &MF) {
365 BitVector AllocSet = TRI.getAllocatableSet(MF);
366
367 for (unsigned R : AllocSet.set_bits())
368 for (MCRegAliasIterator AI(R, &TRI, false); AI.isValid(); ++AI)
369 AllocSet.set(*AI);
370
371 AllocSet.set(Mips::ZERO);
372 AllocSet.set(Mips::ZERO_64);
373
374 Defs |= AllocSet.flip();
375}
376
377void RegDefsUses::addLiveOut(const MachineBasicBlock &MBB,
378 const MachineBasicBlock &SuccBB) {
379 for (const MachineBasicBlock *S : MBB.successors())
380 if (S != &SuccBB)
381 for (const auto &LI : S->liveins())
382 Uses.set(LI.PhysReg.id());
383}
384
385bool RegDefsUses::update(const MachineInstr &MI, unsigned Begin, unsigned End) {
386 BitVector NewDefs(TRI.getNumRegs()), NewUses(TRI.getNumRegs());
387 bool HasHazard = false;
388
389 for (unsigned I = Begin; I != End; ++I) {
390 const MachineOperand &MO = MI.getOperand(I);
391
392 if (MO.isReg() && MO.getReg()) {
393 if (checkRegDefsUses(NewDefs, NewUses, MO.getReg(), MO.isDef())) {
394 LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found register hazard for operand "
395 << I << ": ";
396 MO.dump());
397 HasHazard = true;
398 }
399 }
400 }
401
402 Defs |= NewDefs;
403 Uses |= NewUses;
404
405 return HasHazard;
406}
407
408bool RegDefsUses::checkRegDefsUses(BitVector &NewDefs, BitVector &NewUses,
409 unsigned Reg, bool IsDef) const {
410 if (IsDef) {
411 NewDefs.set(Reg);
412 // check whether Reg has already been defined or used.
413 return (isRegInSet(Defs, Reg) || isRegInSet(Uses, Reg));
414 }
415
416 NewUses.set(Reg);
417 // check whether Reg has already been defined.
418 return isRegInSet(Defs, Reg);
419}
420
421bool RegDefsUses::isRegInSet(const BitVector &RegSet, unsigned Reg) const {
422 // Check Reg and all aliased Registers.
423 for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI)
424 if (RegSet.test(*AI))
425 return true;
426 return false;
427}
428
429bool InspectMemInstr::hasHazard(const MachineInstr &MI) {
430 if (!MI.mayStore() && !MI.mayLoad())
431 return false;
432
433 if (ForbidMemInstr)
434 return true;
435
436 OrigSeenLoad = SeenLoad;
437 OrigSeenStore = SeenStore;
438 SeenLoad |= MI.mayLoad();
439 SeenStore |= MI.mayStore();
440
441 // If MI is an ordered or volatile memory reference, disallow moving
442 // subsequent loads and stores to delay slot.
443 if (MI.hasOrderedMemoryRef() && (OrigSeenLoad || OrigSeenStore)) {
444 ForbidMemInstr = true;
445 return true;
446 }
447
448 return hasHazard_(MI);
449}
450
451bool LoadFromStackOrConst::hasHazard_(const MachineInstr &MI) {
452 if (MI.mayStore())
453 return true;
454
455 if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getPseudoValue())
456 return true;
457
458 if (const PseudoSourceValue *PSV =
459 (*MI.memoperands_begin())->getPseudoValue()) {
461 return false;
462 return !PSV->isConstant(nullptr) && !PSV->isStack();
463 }
464
465 return true;
466}
467
468MemDefsUses::MemDefsUses(const MachineFrameInfo *MFI_)
469 : InspectMemInstr(false), MFI(MFI_) {}
470
471bool MemDefsUses::hasHazard_(const MachineInstr &MI) {
472 bool HasHazard = false;
473
474 // Check underlying object list.
476 if (getUnderlyingObjects(MI, Objs)) {
477 for (ValueType VT : Objs)
478 HasHazard |= updateDefsUses(VT, MI.mayStore());
479 return HasHazard;
480 }
481
482 // No underlying objects found.
483 HasHazard = MI.mayStore() && (OrigSeenLoad || OrigSeenStore);
484 HasHazard |= MI.mayLoad() || OrigSeenStore;
485
486 SeenNoObjLoad |= MI.mayLoad();
487 SeenNoObjStore |= MI.mayStore();
488
489 return HasHazard;
490}
491
492bool MemDefsUses::updateDefsUses(ValueType V, bool MayStore) {
493 if (MayStore)
494 return !Defs.insert(V).second || Uses.count(V) || SeenNoObjStore ||
495 SeenNoObjLoad;
496
497 Uses.insert(V);
498 return Defs.count(V) || SeenNoObjStore;
499}
500
501bool MemDefsUses::
502getUnderlyingObjects(const MachineInstr &MI,
503 SmallVectorImpl<ValueType> &Objects) const {
504 if (!MI.hasOneMemOperand())
505 return false;
506
507 auto & MMO = **MI.memoperands_begin();
508
509 if (const PseudoSourceValue *PSV = MMO.getPseudoValue()) {
510 if (!PSV->isAliased(MFI))
511 return false;
512 Objects.push_back(PSV);
513 return true;
514 }
515
516 if (const Value *V = MMO.getValue()) {
518 ::getUnderlyingObjects(V, Objs);
519
520 for (const Value *UValue : Objs) {
521 if (!isIdentifiedObject(V))
522 return false;
523
524 Objects.push_back(UValue);
525 }
526 return true;
527 }
528
529 return false;
530}
531
532// Replace Branch with the compact branch instruction.
533Iter MipsDelaySlotFiller::replaceWithCompactBranch(MachineBasicBlock &MBB,
534 Iter Branch,
535 const DebugLoc &DL) {
536 const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>();
537 const MipsInstrInfo *TII = STI.getInstrInfo();
538
539 unsigned NewOpcode = TII->getEquivalentCompactForm(Branch);
540 Branch = TII->genInstrWithNewOpc(NewOpcode, Branch);
541
542 auto *ToErase = cast<MachineInstr>(&*std::next(Branch));
543 // Update call info for the Branch.
544 if (ToErase->shouldUpdateAdditionalCallInfo())
545 ToErase->getMF()->moveAdditionalCallInfo(ToErase,
546 cast<MachineInstr>(&*Branch));
547 ToErase->eraseFromParent();
548 return Branch;
549}
550
551// For given opcode returns opcode of corresponding instruction with short
552// delay slot.
553// For the pseudo TAILCALL*_MM instructions return the short delay slot
554// form. Unfortunately, TAILCALL<->b16 is denied as b16 has a limited range
555// that is too short to make use of for tail calls.
556static int getEquivalentCallShort(int Opcode) {
557 switch (Opcode) {
558 case Mips::BGEZAL:
559 return Mips::BGEZALS_MM;
560 case Mips::BLTZAL:
561 return Mips::BLTZALS_MM;
562 case Mips::JAL:
563 case Mips::JAL_MM:
564 return Mips::JALS_MM;
565 case Mips::JALR:
566 return Mips::JALRS_MM;
567 case Mips::JALR16_MM:
568 return Mips::JALRS16_MM;
569 case Mips::TAILCALL_MM:
570 llvm_unreachable("Attempting to shorten the TAILCALL_MM pseudo!");
571 case Mips::TAILCALLREG:
572 return Mips::JR16_MM;
573 default:
574 llvm_unreachable("Unexpected call instruction for microMIPS.");
575 }
576}
577
578/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
579/// We assume there is only one delay slot per delayed instruction.
580bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
581 bool Changed = false;
582 const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>();
583 bool InMicroMipsMode = STI.inMicroMipsMode();
584 const MipsInstrInfo *TII = STI.getInstrInfo();
585
586 for (Iter I = MBB.begin(); I != MBB.end(); ++I) {
587 if (!hasUnoccupiedSlot(&*I))
588 continue;
589
590 // Delay slot filling is disabled at -O0, or in microMIPS32R6.
592 (TM->getOptLevel() != CodeGenOptLevel::None) &&
593 !(InMicroMipsMode && STI.hasMips32r6())) {
594
595 bool Filled = false;
596
597 if (MipsCompactBranchPolicy.getValue() != CB_Always ||
598 !TII->getEquivalentCompactForm(I)) {
599 if (searchBackward(MBB, *I)) {
600 LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot"
601 " in backwards search.\n");
602 Filled = true;
603 } else if (I->isTerminator()) {
604 if (searchSuccBBs(MBB, I)) {
605 Filled = true;
606 LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot"
607 " in successor BB search.\n");
608 }
609 } else if (searchForward(MBB, I)) {
610 LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot"
611 " in forwards search.\n");
612 Filled = true;
613 }
614 }
615
616 if (Filled) {
617 // Get instruction with delay slot.
618 MachineBasicBlock::instr_iterator DSI = I.getInstrIterator();
619
620 if (InMicroMipsMode && TII->getInstSizeInBytes(*std::next(DSI)) == 2 &&
621 DSI->isCall()) {
622 // If instruction in delay slot is 16b change opcode to
623 // corresponding instruction with short delay slot.
624
625 // TODO: Implement an instruction mapping table of 16bit opcodes to
626 // 32bit opcodes so that an instruction can be expanded. This would
627 // save 16 bits as a TAILCALL_MM pseudo requires a fullsized nop.
628 // TODO: Permit b16 when branching backwards to the same function
629 // if it is in range.
630 DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode())));
631 }
632 ++FilledSlots;
633 Changed = true;
634 continue;
635 }
636 }
637
638 // For microMIPS if instruction is BEQ or BNE with one ZERO register, then
639 // instead of adding NOP replace this instruction with the corresponding
640 // compact branch instruction, i.e. BEQZC or BNEZC. Additionally
641 // PseudoReturn and PseudoIndirectBranch are expanded to JR_MM, so they can
642 // be replaced with JRC16_MM.
643
644 // For MIPSR6 attempt to produce the corresponding compact (no delay slot)
645 // form of the CTI. For indirect jumps this will not require inserting a
646 // NOP and for branches will hopefully avoid requiring a NOP.
647 if ((InMicroMipsMode ||
649 TII->getEquivalentCompactForm(I)) {
650 I = replaceWithCompactBranch(MBB, I, I->getDebugLoc());
651 Changed = true;
652 continue;
653 }
654
655 // Bundle the NOP to the instruction with the delay slot.
656 LLVM_DEBUG(dbgs() << DEBUG_TYPE << ": could not fill delay slot for ";
657 I->dump());
658 TII->insertNop(MBB, std::next(I), I->getDebugLoc());
659 MIBundleBuilder(MBB, I, std::next(I, 2));
660 ++FilledSlots;
661 Changed = true;
662 }
663
664 return Changed;
665}
666
667template <typename IterTy>
668bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin,
669 IterTy End, RegDefsUses &RegDU,
670 InspectMemInstr &IM, Iter Slot,
671 IterTy &Filler) const {
672 for (IterTy I = Begin; I != End;) {
673 IterTy CurrI = I;
674 ++I;
675 LLVM_DEBUG(dbgs() << DEBUG_TYPE ": checking instruction: "; CurrI->dump());
676 // Skip debug value.
677 // Instruction TargetOpcode::JUMP_TABLE_DEBUG_INFO is only used to note
678 // jump table debug info.
679 if (CurrI->isDebugInstr() || CurrI->isJumpTableDebugInfo()) {
680 LLVM_DEBUG(dbgs() << DEBUG_TYPE ": ignoring debug instruction: ";
681 CurrI->dump());
682 continue;
683 }
684
685 if (CurrI->isBundle()) {
686 LLVM_DEBUG(dbgs() << DEBUG_TYPE ": ignoring BUNDLE instruction: ";
687 CurrI->dump());
688 // However, we still need to update the register def-use information.
689 RegDU.update(*CurrI, 0, CurrI->getNumOperands());
690 continue;
691 }
692
693 if (terminateSearch(*CurrI)) {
694 LLVM_DEBUG(dbgs() << DEBUG_TYPE ": should terminate search: ";
695 CurrI->dump());
696 break;
697 }
698
699 assert((!CurrI->isCall() && !CurrI->isReturn() && !CurrI->isBranch()) &&
700 "Cannot put calls, returns or branches in delay slot.");
701
702 if (CurrI->isKill()) {
703 CurrI->eraseFromParent();
704 continue;
705 }
706
707 if (delayHasHazard(*CurrI, RegDU, IM))
708 continue;
709
710 const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>();
711 bool InMicroMipsMode = STI.inMicroMipsMode();
712 const MipsInstrInfo *TII = STI.getInstrInfo();
713 unsigned Opcode = (*Slot).getOpcode();
714
715 // In mips1-4, should not put mflo into the delay slot for the return.
716 if ((IsMFLOMFHI(CurrI->getOpcode())) &&
717 (!STI.hasMips32() && !STI.hasMips5()))
718 continue;
719
720 // This is complicated by the tail call optimization. For non-PIC code
721 // there is only a 32bit sized unconditional branch which can be assumed
722 // to be able to reach the target. b16 only has a range of +/- 1 KB.
723 // It's entirely possible that the target function is reachable with b16
724 // but we don't have enough information to make that decision.
725 if (InMicroMipsMode && TII->getInstSizeInBytes(*CurrI) == 2 &&
726 (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch ||
727 Opcode == Mips::PseudoIndirectBranch_MM ||
728 Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL))
729 continue;
730 // Instructions LWP/SWP and MOVEP should not be in a delay slot as that
731 // results in unpredictable behaviour
732 if (InMicroMipsMode && (Opcode == Mips::LWP_MM || Opcode == Mips::SWP_MM ||
733 Opcode == Mips::MOVEP_MM))
734 continue;
735
736 Filler = CurrI;
737 LLVM_DEBUG(dbgs() << DEBUG_TYPE ": found instruction for delay slot: ";
738 CurrI->dump());
739
740 return true;
741 }
742
743 return false;
744}
745
746bool MipsDelaySlotFiller::searchBackward(MachineBasicBlock &MBB,
747 MachineInstr &Slot) const {
749 return false;
750
751 auto *Fn = MBB.getParent();
752 RegDefsUses RegDU(*Fn->getSubtarget().getRegisterInfo());
753 MemDefsUses MemDU(&Fn->getFrameInfo());
754 ReverseIter Filler;
755
756 RegDU.init(Slot);
757
759 if (!searchRange(MBB, ++SlotI.getReverse(), MBB.rend(), RegDU, MemDU, Slot,
760 Filler)) {
761 LLVM_DEBUG(dbgs() << DEBUG_TYPE ": could not find instruction for delay "
762 "slot using backwards search.\n");
763 return false;
764 }
765
766 MBB.splice(std::next(SlotI), &MBB, Filler.getReverse());
767 MIBundleBuilder(MBB, SlotI, std::next(SlotI, 2));
768 ++UsefulSlots;
769 return true;
770}
771
772bool MipsDelaySlotFiller::searchForward(MachineBasicBlock &MBB,
773 Iter Slot) const {
774 // Can handle only calls.
775 if (DisableForwardSearch || !Slot->isCall())
776 return false;
777
778 RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo());
779 NoMemInstr NM;
780 Iter Filler;
781
782 RegDU.setCallerSaved(*Slot);
783
784 if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Slot, Filler)) {
785 LLVM_DEBUG(dbgs() << DEBUG_TYPE ": could not find instruction for delay "
786 "slot using forwards search.\n");
787 return false;
788 }
789
790 MBB.splice(std::next(Slot), &MBB, Filler);
791 MIBundleBuilder(MBB, Slot, std::next(Slot, 2));
792 ++UsefulSlots;
793 return true;
794}
795
796bool MipsDelaySlotFiller::searchSuccBBs(MachineBasicBlock &MBB,
797 Iter Slot) const {
799 return false;
800
801 MachineBasicBlock *SuccBB = selectSuccBB(MBB);
802
803 if (!SuccBB)
804 return false;
805
806 RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo());
807 bool HasMultipleSuccs = false;
808 BB2BrMap BrMap;
809 std::unique_ptr<InspectMemInstr> IM;
810 Iter Filler;
811 auto *Fn = MBB.getParent();
812
813 // Iterate over SuccBB's predecessor list.
814 for (MachineBasicBlock *Pred : SuccBB->predecessors())
815 if (!examinePred(*Pred, *SuccBB, RegDU, HasMultipleSuccs, BrMap))
816 return false;
817
818 // Do not allow moving instructions which have unallocatable register operands
819 // across basic block boundaries.
820 RegDU.setUnallocatableRegs(*Fn);
821
822 // Only allow moving loads from stack or constants if any of the SuccBB's
823 // predecessors have multiple successors.
824 if (HasMultipleSuccs) {
825 IM.reset(new LoadFromStackOrConst());
826 } else {
827 const MachineFrameInfo &MFI = Fn->getFrameInfo();
828 IM.reset(new MemDefsUses(&MFI));
829 }
830
831 if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Slot,
832 Filler))
833 return false;
834
835 insertDelayFiller(Filler, BrMap);
836 addLiveInRegs(Filler, *SuccBB);
837 Filler->eraseFromParent();
838
839 return true;
840}
841
842MachineBasicBlock *
843MipsDelaySlotFiller::selectSuccBB(MachineBasicBlock &B) const {
844 if (B.succ_empty())
845 return nullptr;
846
847 // Select the successor with the larget edge weight.
848 auto &Prob = getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
849 MachineBasicBlock *S =
850 *llvm::max_element(B.successors(), [&](const MachineBasicBlock *Dst0,
851 const MachineBasicBlock *Dst1) {
852 return Prob.getEdgeProbability(&B, Dst0) <
853 Prob.getEdgeProbability(&B, Dst1);
854 });
855 return S->isEHPad() ? nullptr : S;
856}
857
858std::pair<MipsInstrInfo::BranchType, MachineInstr *>
859MipsDelaySlotFiller::getBranch(MachineBasicBlock &MBB,
860 const MachineBasicBlock &Dst) const {
861 const MipsInstrInfo *TII =
862 MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo();
863 MachineBasicBlock *TrueBB = nullptr, *FalseBB = nullptr;
864 SmallVector<MachineInstr*, 2> BranchInstrs;
866
868 TII->analyzeBranch(MBB, TrueBB, FalseBB, Cond, false, BranchInstrs);
869
871 return std::make_pair(R, nullptr);
872
874 if (!hasUnoccupiedSlot(BranchInstrs[0]))
875 return std::make_pair(MipsInstrInfo::BT_None, nullptr);
876
877 assert(((R != MipsInstrInfo::BT_Uncond) || (TrueBB == &Dst)));
878
879 return std::make_pair(R, BranchInstrs[0]);
880 }
881
882 assert((TrueBB == &Dst) || (FalseBB == &Dst));
883
884 // Examine the conditional branch. See if its slot is occupied.
885 if (hasUnoccupiedSlot(BranchInstrs[0]))
886 return std::make_pair(MipsInstrInfo::BT_Cond, BranchInstrs[0]);
887
888 // If that fails, try the unconditional branch.
889 if (hasUnoccupiedSlot(BranchInstrs[1]) && (FalseBB == &Dst))
890 return std::make_pair(MipsInstrInfo::BT_Uncond, BranchInstrs[1]);
891
892 return std::make_pair(MipsInstrInfo::BT_None, nullptr);
893}
894
895bool MipsDelaySlotFiller::examinePred(MachineBasicBlock &Pred,
896 const MachineBasicBlock &Succ,
897 RegDefsUses &RegDU,
898 bool &HasMultipleSuccs,
899 BB2BrMap &BrMap) const {
900 std::pair<MipsInstrInfo::BranchType, MachineInstr *> P =
901 getBranch(Pred, Succ);
902
903 // Return if either getBranch wasn't able to analyze the branches or there
904 // were no branches with unoccupied slots.
905 if (P.first == MipsInstrInfo::BT_None)
906 return false;
907
908 if ((P.first != MipsInstrInfo::BT_Uncond) &&
909 (P.first != MipsInstrInfo::BT_NoBranch)) {
910 HasMultipleSuccs = true;
911 RegDU.addLiveOut(Pred, Succ);
912 }
913
914 BrMap[&Pred] = P.second;
915 return true;
916}
917
918bool MipsDelaySlotFiller::delayHasHazard(const MachineInstr &Candidate,
919 RegDefsUses &RegDU,
920 InspectMemInstr &IM) const {
921 assert(!Candidate.isKill() &&
922 "KILL instructions should have been eliminated at this point.");
923
924 bool HasHazard = Candidate.isImplicitDef();
925
926 HasHazard |= IM.hasHazard(Candidate);
927 HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands());
928
929 return HasHazard;
930}
931
932bool MipsDelaySlotFiller::terminateSearch(const MachineInstr &Candidate) const {
933 return (Candidate.isTerminator() || Candidate.isCall() ||
934 Candidate.isPosition() || Candidate.isInlineAsm() ||
935 Candidate.hasUnmodeledSideEffects());
936}
937
938/// createMipsDelaySlotFillerPass - Returns a pass that fills in delay
939/// slots in Mips MachineFunctions
941 return new MipsDelaySlotFiller();
942}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
static const Function * getParent(const Value *V)
basic Basic Alias true
This file implements the BitVector class.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
static bool hasHazard(StateT InitialState, function_ref< HazardFnResult(StateT &, const MachineInstr &)> IsHazard, function_ref< void(StateT &, const MachineInstr &)> UpdateState, const MachineBasicBlock *InitialMBB, MachineBasicBlock::const_reverse_instr_iterator InitialI)
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
static bool hasUnoccupiedSlot(const MachineInstr *MI)
static cl::opt< bool > DisableDelaySlotFiller("disable-mips-delay-filler", cl::init(false), cl::desc("Fill all delay slots with NOPs."), cl::Hidden)
static cl::opt< bool > DisableBackwardSearch("disable-mips-df-backward-search", cl::init(false), cl::desc("Disallow MIPS delay filler to search backward."), cl::Hidden)
static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB)
This function adds registers Filler defines to MBB's live-in register list.
static cl::opt< bool > DisableSuccBBSearch("disable-mips-df-succbb-search", cl::init(true), cl::desc("Disallow MIPS delay filler to search successor basic blocks."), cl::Hidden)
const BB2BrMap & BrMap
static cl::opt< bool > DisableForwardSearch("disable-mips-df-forward-search", cl::init(true), cl::desc("Disallow MIPS delay filler to search forward."), cl::Hidden)
cl::opt< CompactBranchPolicy > MipsCompactBranchPolicy
static int getEquivalentCallShort(int Opcode)
#define IsMFLOMFHI(instr)
Definition Mips.h:20
#define P(N)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file defines the PointerUnion class, which is a discriminated union of pointer types.
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
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
#define LLVM_DEBUG(...)
Definition Debug.h:114
AnalysisUsage & addRequired()
bool test(unsigned Idx) const
Definition BitVector.h:480
BitVector & reset()
Definition BitVector.h:411
BitVector & set()
Definition BitVector.h:370
BitVector & flip()
Definition BitVector.h:450
iterator_range< const_set_bits_iterator > set_bits() const
Definition BitVector.h:159
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
Helper class for constructing bundles of MachineInstrs.
MIBundleBuilder & append(MachineInstr *MI)
Insert MI into MBB by appending it to the instructions in the bundle.
bool isEHPad() const
Returns true if the block is a landing pad.
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
bool isPosition() const
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
bool isImplicitDef() const
bool isCall(QueryType Type=AnyInBundle) const
unsigned getNumOperands() const
Retuns the total number of operands.
bool isInlineAsm() const
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
bool isKill() const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void dump() const
Register getReg() const
getReg - Returns the register number.
bool hasMips32r6() const
bool inMicroMipsMode() const
const MipsInstrInfo * getInstrInfo() const override
bool hasMips5() const
bool hasMips32() const
void push_back(const T &Elt)
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
BitVector getAllocatableSet(const MachineFunction &MF, const TargetRegisterClass *RC=nullptr) const
Returns a bitset indexed by register number indicating if a register is allocatable or not.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ CB_Never
The policy 'never' may in some circumstances or for some ISAs not be absolutely adhered to.
@ CB_Always
'always' may in some circumstances may not be absolutely adhered to, there may not be a corresponding...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2042
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
FunctionPass * createMipsDelaySlotFillerPass()
createMipsDelaySlotFillerPass - Returns a pass that fills in delay slots in Mips MachineFunctions
LLVM_ABI void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=MaxLookupSearchDepth)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.