1 //===-- MipsHazardSchedule.cpp - Workaround pipeline hazards --------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// This pass is used to workaround certain pipeline hazards. For now, this
11 /// covers compact branch hazards. In future this pass can be extended to other
12 /// pipeline hazards, such as various MIPS1 hazards, processor errata that
13 /// require instruction reorganization, etc.
15 /// This pass has to run after the delay slot filler as that pass can introduce
16 /// pipeline hazards, hence the existing hazard recognizer is not suitable.
18 /// Hazards handled: forbidden slots for MIPSR6.
20 /// A forbidden slot hazard occurs when a compact branch instruction is executed
21 /// and the adjacent instruction in memory is a control transfer instruction
22 /// such as a branch or jump, ERET, ERETNC, DERET, WAIT and PAUSE.
26 /// 0x8004 bnec a1,v0,<P+0x18>
27 /// 0x8008 beqc a1,a2,<P+0x54>
29 /// In such cases, the processor is required to signal a Reserved Instruction
32 /// Here, if the instruction at 0x8004 is executed, the processor will raise an
33 /// exception as there is a control transfer instruction at 0x8008.
35 /// There are two sources of forbidden slot hazards:
37 /// A) A previous pass has created a compact branch directly.
38 /// B) Transforming a delay slot branch into compact branch. This case can be
39 /// difficult to process as lookahead for hazards is insufficient, as
40 /// backwards delay slot fillling can also produce hazards in previously
41 /// processed instuctions.
43 //===----------------------------------------------------------------------===//
46 #include "MipsInstrInfo.h"
47 #include "MipsSEInstrInfo.h"
48 #include "MipsTargetMachine.h"
49 #include "llvm/ADT/Statistic.h"
50 #include "llvm/CodeGen/MachineFunctionPass.h"
51 #include "llvm/CodeGen/MachineInstrBuilder.h"
52 #include "llvm/IR/Function.h"
53 #include "llvm/Target/TargetInstrInfo.h"
54 #include "llvm/Target/TargetMachine.h"
55 #include "llvm/Target/TargetRegisterInfo.h"
59 #define DEBUG_TYPE "mips-hazard-schedule"
61 STATISTIC(NumInsertedNops, "Number of nops inserted");
65 typedef MachineBasicBlock::iterator Iter;
66 typedef MachineBasicBlock::reverse_iterator ReverseIter;
68 class MipsHazardSchedule : public MachineFunctionPass {
71 MipsHazardSchedule() : MachineFunctionPass(ID) {}
73 StringRef getPassName() const override { return "Mips Hazard Schedule"; }
75 bool runOnMachineFunction(MachineFunction &F) override;
77 MachineFunctionProperties getRequiredProperties() const override {
78 return MachineFunctionProperties().set(
79 MachineFunctionProperties::Property::NoVRegs);
86 char MipsHazardSchedule::ID = 0;
87 } // end of anonymous namespace
89 /// Returns a pass that clears pipeline hazards.
90 FunctionPass *llvm::createMipsHazardSchedule() {
91 return new MipsHazardSchedule();
94 // Find the next real instruction from the current position in current basic
96 static Iter getNextMachineInstrInBB(Iter Position) {
97 Iter I = Position, E = Position->getParent()->end();
98 I = std::find_if_not(I, E,
99 [](const Iter &Insn) { return Insn->isTransient(); });
104 // Find the next real instruction from the current position, looking through
105 // basic block boundaries.
106 static std::pair<Iter, bool> getNextMachineInstr(Iter Position, MachineBasicBlock * Parent) {
107 if (Position == Parent->end()) {
109 MachineBasicBlock *Succ = Parent->getNextNode();
110 if (Succ != nullptr && Parent->isSuccessor(Succ)) {
111 Position = Succ->begin();
114 return std::make_pair(Position, true);
116 } while (Parent->empty());
119 Iter Instr = getNextMachineInstrInBB(Position);
120 if (Instr == Parent->end()) {
121 return getNextMachineInstr(Instr, Parent);
123 return std::make_pair(Instr, false);
126 bool MipsHazardSchedule::runOnMachineFunction(MachineFunction &MF) {
128 const MipsSubtarget *STI =
129 &static_cast<const MipsSubtarget &>(MF.getSubtarget());
131 // Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6.
132 if (!STI->hasMips32r6() || STI->inMicroMipsMode())
135 bool Changed = false;
136 const MipsInstrInfo *TII = STI->getInstrInfo();
138 for (MachineFunction::iterator FI = MF.begin(); FI != MF.end(); ++FI) {
139 for (Iter I = FI->begin(); I != FI->end(); ++I) {
141 // Forbidden slot hazard handling. Use lookahead over state.
142 if (!TII->HasForbiddenSlot(*I))
146 bool LastInstInFunction =
147 std::next(I) == FI->end() && std::next(FI) == MF.end();
148 if (!LastInstInFunction) {
149 std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI);
150 LastInstInFunction |= Res.second;
154 if (LastInstInFunction || !TII->SafeInForbiddenSlot(*Inst)) {
157 .append(BuildMI(MF, I->getDebugLoc(), TII->get(Mips::NOP)));