xref: /aosp_15_r20/external/llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- PPCHazardRecognizers.cpp - PowerPC Hazard Recognizer Impls --------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements hazard recognizers for scheduling on PowerPC processors.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "PPCHazardRecognizers.h"
15*9880d681SAndroid Build Coastguard Worker #include "PPC.h"
16*9880d681SAndroid Build Coastguard Worker #include "PPCInstrInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "PPCTargetMachine.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ScheduleDAG.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
22*9880d681SAndroid Build Coastguard Worker using namespace llvm;
23*9880d681SAndroid Build Coastguard Worker 
24*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "pre-RA-sched"
25*9880d681SAndroid Build Coastguard Worker 
isLoadAfterStore(SUnit * SU)26*9880d681SAndroid Build Coastguard Worker bool PPCDispatchGroupSBHazardRecognizer::isLoadAfterStore(SUnit *SU) {
27*9880d681SAndroid Build Coastguard Worker   // FIXME: Move this.
28*9880d681SAndroid Build Coastguard Worker   if (isBCTRAfterSet(SU))
29*9880d681SAndroid Build Coastguard Worker     return true;
30*9880d681SAndroid Build Coastguard Worker 
31*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
32*9880d681SAndroid Build Coastguard Worker   if (!MCID)
33*9880d681SAndroid Build Coastguard Worker     return false;
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker   if (!MCID->mayLoad())
36*9880d681SAndroid Build Coastguard Worker     return false;
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker   // SU is a load; for any predecessors in this dispatch group, that are stores,
39*9880d681SAndroid Build Coastguard Worker   // and with which we have an ordering dependency, return true.
40*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, ie = (unsigned) SU->Preds.size(); i != ie; ++i) {
41*9880d681SAndroid Build Coastguard Worker     const MCInstrDesc *PredMCID = DAG->getInstrDesc(SU->Preds[i].getSUnit());
42*9880d681SAndroid Build Coastguard Worker     if (!PredMCID || !PredMCID->mayStore())
43*9880d681SAndroid Build Coastguard Worker       continue;
44*9880d681SAndroid Build Coastguard Worker 
45*9880d681SAndroid Build Coastguard Worker     if (!SU->Preds[i].isNormalMemory() && !SU->Preds[i].isBarrier())
46*9880d681SAndroid Build Coastguard Worker       continue;
47*9880d681SAndroid Build Coastguard Worker 
48*9880d681SAndroid Build Coastguard Worker     for (unsigned j = 0, je = CurGroup.size(); j != je; ++j)
49*9880d681SAndroid Build Coastguard Worker       if (SU->Preds[i].getSUnit() == CurGroup[j])
50*9880d681SAndroid Build Coastguard Worker         return true;
51*9880d681SAndroid Build Coastguard Worker   }
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker   return false;
54*9880d681SAndroid Build Coastguard Worker }
55*9880d681SAndroid Build Coastguard Worker 
isBCTRAfterSet(SUnit * SU)56*9880d681SAndroid Build Coastguard Worker bool PPCDispatchGroupSBHazardRecognizer::isBCTRAfterSet(SUnit *SU) {
57*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
58*9880d681SAndroid Build Coastguard Worker   if (!MCID)
59*9880d681SAndroid Build Coastguard Worker     return false;
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker   if (!MCID->isBranch())
62*9880d681SAndroid Build Coastguard Worker     return false;
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker   // SU is a branch; for any predecessors in this dispatch group, with which we
65*9880d681SAndroid Build Coastguard Worker   // have a data dependence and set the counter register, return true.
66*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, ie = (unsigned) SU->Preds.size(); i != ie; ++i) {
67*9880d681SAndroid Build Coastguard Worker     const MCInstrDesc *PredMCID = DAG->getInstrDesc(SU->Preds[i].getSUnit());
68*9880d681SAndroid Build Coastguard Worker     if (!PredMCID || PredMCID->getSchedClass() != PPC::Sched::IIC_SprMTSPR)
69*9880d681SAndroid Build Coastguard Worker       continue;
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker     if (SU->Preds[i].isCtrl())
72*9880d681SAndroid Build Coastguard Worker       continue;
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker     for (unsigned j = 0, je = CurGroup.size(); j != je; ++j)
75*9880d681SAndroid Build Coastguard Worker       if (SU->Preds[i].getSUnit() == CurGroup[j])
76*9880d681SAndroid Build Coastguard Worker         return true;
77*9880d681SAndroid Build Coastguard Worker   }
78*9880d681SAndroid Build Coastguard Worker 
79*9880d681SAndroid Build Coastguard Worker   return false;
80*9880d681SAndroid Build Coastguard Worker }
81*9880d681SAndroid Build Coastguard Worker 
82*9880d681SAndroid Build Coastguard Worker // FIXME: Remove this when we don't need this:
83*9880d681SAndroid Build Coastguard Worker namespace llvm { namespace PPC { extern int getNonRecordFormOpcode(uint16_t); } }
84*9880d681SAndroid Build Coastguard Worker 
85*9880d681SAndroid Build Coastguard Worker // FIXME: A lot of code in PPCDispatchGroupSBHazardRecognizer is P7 specific.
86*9880d681SAndroid Build Coastguard Worker 
mustComeFirst(const MCInstrDesc * MCID,unsigned & NSlots)87*9880d681SAndroid Build Coastguard Worker bool PPCDispatchGroupSBHazardRecognizer::mustComeFirst(const MCInstrDesc *MCID,
88*9880d681SAndroid Build Coastguard Worker                                                        unsigned &NSlots) {
89*9880d681SAndroid Build Coastguard Worker   // FIXME: Indirectly, this information is contained in the itinerary, and
90*9880d681SAndroid Build Coastguard Worker   // we should derive it from there instead of separately specifying it
91*9880d681SAndroid Build Coastguard Worker   // here.
92*9880d681SAndroid Build Coastguard Worker   unsigned IIC = MCID->getSchedClass();
93*9880d681SAndroid Build Coastguard Worker   switch (IIC) {
94*9880d681SAndroid Build Coastguard Worker   default:
95*9880d681SAndroid Build Coastguard Worker     NSlots = 1;
96*9880d681SAndroid Build Coastguard Worker     break;
97*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_IntDivW:
98*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_IntDivD:
99*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLoadUpd:
100*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLDU:
101*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLFDU:
102*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLFDUX:
103*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLHA:
104*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLHAU:
105*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLWA:
106*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStSTDU:
107*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStSTFDU:
108*9880d681SAndroid Build Coastguard Worker     NSlots = 2;
109*9880d681SAndroid Build Coastguard Worker     break;
110*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLoadUpdX:
111*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLDUX:
112*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLHAUX:
113*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLWARX:
114*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStLDARX:
115*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStSTDUX:
116*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStSTDCX:
117*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_LdStSTWCX:
118*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_BrMCRX: // mtcr
119*9880d681SAndroid Build Coastguard Worker   // FIXME: Add sync/isync (here and in the itinerary).
120*9880d681SAndroid Build Coastguard Worker     NSlots = 4;
121*9880d681SAndroid Build Coastguard Worker     break;
122*9880d681SAndroid Build Coastguard Worker   }
123*9880d681SAndroid Build Coastguard Worker 
124*9880d681SAndroid Build Coastguard Worker   // FIXME: record-form instructions need a different itinerary class.
125*9880d681SAndroid Build Coastguard Worker   if (NSlots == 1 && PPC::getNonRecordFormOpcode(MCID->getOpcode()) != -1)
126*9880d681SAndroid Build Coastguard Worker     NSlots = 2;
127*9880d681SAndroid Build Coastguard Worker 
128*9880d681SAndroid Build Coastguard Worker   switch (IIC) {
129*9880d681SAndroid Build Coastguard Worker   default:
130*9880d681SAndroid Build Coastguard Worker     // All multi-slot instructions must come first.
131*9880d681SAndroid Build Coastguard Worker     return NSlots > 1;
132*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_BrCR: // cr logicals
133*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_SprMFCR:
134*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_SprMFCRF:
135*9880d681SAndroid Build Coastguard Worker   case PPC::Sched::IIC_SprMTSPR:
136*9880d681SAndroid Build Coastguard Worker     return true;
137*9880d681SAndroid Build Coastguard Worker   }
138*9880d681SAndroid Build Coastguard Worker }
139*9880d681SAndroid Build Coastguard Worker 
140*9880d681SAndroid Build Coastguard Worker ScheduleHazardRecognizer::HazardType
getHazardType(SUnit * SU,int Stalls)141*9880d681SAndroid Build Coastguard Worker PPCDispatchGroupSBHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
142*9880d681SAndroid Build Coastguard Worker   if (Stalls == 0 && isLoadAfterStore(SU))
143*9880d681SAndroid Build Coastguard Worker     return NoopHazard;
144*9880d681SAndroid Build Coastguard Worker 
145*9880d681SAndroid Build Coastguard Worker   return ScoreboardHazardRecognizer::getHazardType(SU, Stalls);
146*9880d681SAndroid Build Coastguard Worker }
147*9880d681SAndroid Build Coastguard Worker 
ShouldPreferAnother(SUnit * SU)148*9880d681SAndroid Build Coastguard Worker bool PPCDispatchGroupSBHazardRecognizer::ShouldPreferAnother(SUnit *SU) {
149*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
150*9880d681SAndroid Build Coastguard Worker   unsigned NSlots;
151*9880d681SAndroid Build Coastguard Worker   if (MCID && mustComeFirst(MCID, NSlots) && CurSlots)
152*9880d681SAndroid Build Coastguard Worker     return true;
153*9880d681SAndroid Build Coastguard Worker 
154*9880d681SAndroid Build Coastguard Worker   return ScoreboardHazardRecognizer::ShouldPreferAnother(SU);
155*9880d681SAndroid Build Coastguard Worker }
156*9880d681SAndroid Build Coastguard Worker 
PreEmitNoops(SUnit * SU)157*9880d681SAndroid Build Coastguard Worker unsigned PPCDispatchGroupSBHazardRecognizer::PreEmitNoops(SUnit *SU) {
158*9880d681SAndroid Build Coastguard Worker   // We only need to fill out a maximum of 5 slots here: The 6th slot could
159*9880d681SAndroid Build Coastguard Worker   // only be a second branch, and otherwise the next instruction will start a
160*9880d681SAndroid Build Coastguard Worker   // new group.
161*9880d681SAndroid Build Coastguard Worker   if (isLoadAfterStore(SU) && CurSlots < 6) {
162*9880d681SAndroid Build Coastguard Worker     unsigned Directive =
163*9880d681SAndroid Build Coastguard Worker         DAG->MF.getSubtarget<PPCSubtarget>().getDarwinDirective();
164*9880d681SAndroid Build Coastguard Worker     // If we're using a special group-terminating nop, then we need only one.
165*9880d681SAndroid Build Coastguard Worker     // FIXME: the same for P9 as previous gen until POWER9 scheduling is ready
166*9880d681SAndroid Build Coastguard Worker     if (Directive == PPC::DIR_PWR6 || Directive == PPC::DIR_PWR7 ||
167*9880d681SAndroid Build Coastguard Worker         Directive == PPC::DIR_PWR8 || Directive == PPC::DIR_PWR9)
168*9880d681SAndroid Build Coastguard Worker       return 1;
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker     return 5 - CurSlots;
171*9880d681SAndroid Build Coastguard Worker   }
172*9880d681SAndroid Build Coastguard Worker 
173*9880d681SAndroid Build Coastguard Worker   return ScoreboardHazardRecognizer::PreEmitNoops(SU);
174*9880d681SAndroid Build Coastguard Worker }
175*9880d681SAndroid Build Coastguard Worker 
EmitInstruction(SUnit * SU)176*9880d681SAndroid Build Coastguard Worker void PPCDispatchGroupSBHazardRecognizer::EmitInstruction(SUnit *SU) {
177*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
178*9880d681SAndroid Build Coastguard Worker   if (MCID) {
179*9880d681SAndroid Build Coastguard Worker     if (CurSlots == 5 || (MCID->isBranch() && CurBranches == 1)) {
180*9880d681SAndroid Build Coastguard Worker       CurGroup.clear();
181*9880d681SAndroid Build Coastguard Worker       CurSlots = CurBranches = 0;
182*9880d681SAndroid Build Coastguard Worker     } else {
183*9880d681SAndroid Build Coastguard Worker       DEBUG(dbgs() << "**** Adding to dispatch group: SU(" <<
184*9880d681SAndroid Build Coastguard Worker                       SU->NodeNum << "): ");
185*9880d681SAndroid Build Coastguard Worker       DEBUG(DAG->dumpNode(SU));
186*9880d681SAndroid Build Coastguard Worker 
187*9880d681SAndroid Build Coastguard Worker       unsigned NSlots;
188*9880d681SAndroid Build Coastguard Worker       bool MustBeFirst = mustComeFirst(MCID, NSlots);
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker       // If this instruction must come first, but does not, then it starts a
191*9880d681SAndroid Build Coastguard Worker       // new group.
192*9880d681SAndroid Build Coastguard Worker       if (MustBeFirst && CurSlots) {
193*9880d681SAndroid Build Coastguard Worker         CurSlots = CurBranches = 0;
194*9880d681SAndroid Build Coastguard Worker         CurGroup.clear();
195*9880d681SAndroid Build Coastguard Worker       }
196*9880d681SAndroid Build Coastguard Worker 
197*9880d681SAndroid Build Coastguard Worker       CurSlots += NSlots;
198*9880d681SAndroid Build Coastguard Worker       CurGroup.push_back(SU);
199*9880d681SAndroid Build Coastguard Worker 
200*9880d681SAndroid Build Coastguard Worker       if (MCID->isBranch())
201*9880d681SAndroid Build Coastguard Worker         ++CurBranches;
202*9880d681SAndroid Build Coastguard Worker     }
203*9880d681SAndroid Build Coastguard Worker   }
204*9880d681SAndroid Build Coastguard Worker 
205*9880d681SAndroid Build Coastguard Worker   return ScoreboardHazardRecognizer::EmitInstruction(SU);
206*9880d681SAndroid Build Coastguard Worker }
207*9880d681SAndroid Build Coastguard Worker 
AdvanceCycle()208*9880d681SAndroid Build Coastguard Worker void PPCDispatchGroupSBHazardRecognizer::AdvanceCycle() {
209*9880d681SAndroid Build Coastguard Worker   return ScoreboardHazardRecognizer::AdvanceCycle();
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker 
RecedeCycle()212*9880d681SAndroid Build Coastguard Worker void PPCDispatchGroupSBHazardRecognizer::RecedeCycle() {
213*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Bottom-up scheduling not supported");
214*9880d681SAndroid Build Coastguard Worker }
215*9880d681SAndroid Build Coastguard Worker 
Reset()216*9880d681SAndroid Build Coastguard Worker void PPCDispatchGroupSBHazardRecognizer::Reset() {
217*9880d681SAndroid Build Coastguard Worker   CurGroup.clear();
218*9880d681SAndroid Build Coastguard Worker   CurSlots = CurBranches = 0;
219*9880d681SAndroid Build Coastguard Worker   return ScoreboardHazardRecognizer::Reset();
220*9880d681SAndroid Build Coastguard Worker }
221*9880d681SAndroid Build Coastguard Worker 
EmitNoop()222*9880d681SAndroid Build Coastguard Worker void PPCDispatchGroupSBHazardRecognizer::EmitNoop() {
223*9880d681SAndroid Build Coastguard Worker   unsigned Directive =
224*9880d681SAndroid Build Coastguard Worker       DAG->MF.getSubtarget<PPCSubtarget>().getDarwinDirective();
225*9880d681SAndroid Build Coastguard Worker   // If the group has now filled all of its slots, or if we're using a special
226*9880d681SAndroid Build Coastguard Worker   // group-terminating nop, the group is complete.
227*9880d681SAndroid Build Coastguard Worker   // FIXME: the same for P9 as previous gen until POWER9 scheduling is ready
228*9880d681SAndroid Build Coastguard Worker   if (Directive == PPC::DIR_PWR6 || Directive == PPC::DIR_PWR7 ||
229*9880d681SAndroid Build Coastguard Worker       Directive == PPC::DIR_PWR8 || Directive == PPC::DIR_PWR8 ||
230*9880d681SAndroid Build Coastguard Worker       CurSlots == 6) {
231*9880d681SAndroid Build Coastguard Worker     CurGroup.clear();
232*9880d681SAndroid Build Coastguard Worker     CurSlots = CurBranches = 0;
233*9880d681SAndroid Build Coastguard Worker   } else {
234*9880d681SAndroid Build Coastguard Worker     CurGroup.push_back(nullptr);
235*9880d681SAndroid Build Coastguard Worker     ++CurSlots;
236*9880d681SAndroid Build Coastguard Worker   }
237*9880d681SAndroid Build Coastguard Worker }
238*9880d681SAndroid Build Coastguard Worker 
239*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
240*9880d681SAndroid Build Coastguard Worker // PowerPC 970 Hazard Recognizer
241*9880d681SAndroid Build Coastguard Worker //
242*9880d681SAndroid Build Coastguard Worker // This models the dispatch group formation of the PPC970 processor.  Dispatch
243*9880d681SAndroid Build Coastguard Worker // groups are bundles of up to five instructions that can contain various mixes
244*9880d681SAndroid Build Coastguard Worker // of instructions.  The PPC970 can dispatch a peak of 4 non-branch and one
245*9880d681SAndroid Build Coastguard Worker // branch instruction per-cycle.
246*9880d681SAndroid Build Coastguard Worker //
247*9880d681SAndroid Build Coastguard Worker // There are a number of restrictions to dispatch group formation: some
248*9880d681SAndroid Build Coastguard Worker // instructions can only be issued in the first slot of a dispatch group, & some
249*9880d681SAndroid Build Coastguard Worker // instructions fill an entire dispatch group.  Additionally, only branches can
250*9880d681SAndroid Build Coastguard Worker // issue in the 5th (last) slot.
251*9880d681SAndroid Build Coastguard Worker //
252*9880d681SAndroid Build Coastguard Worker // Finally, there are a number of "structural" hazards on the PPC970.  These
253*9880d681SAndroid Build Coastguard Worker // conditions cause large performance penalties due to misprediction, recovery,
254*9880d681SAndroid Build Coastguard Worker // and replay logic that has to happen.  These cases include setting a CTR and
255*9880d681SAndroid Build Coastguard Worker // branching through it in the same dispatch group, and storing to an address,
256*9880d681SAndroid Build Coastguard Worker // then loading from the same address within a dispatch group.  To avoid these
257*9880d681SAndroid Build Coastguard Worker // conditions, we insert no-op instructions when appropriate.
258*9880d681SAndroid Build Coastguard Worker //
259*9880d681SAndroid Build Coastguard Worker // FIXME: This is missing some significant cases:
260*9880d681SAndroid Build Coastguard Worker //   1. Modeling of microcoded instructions.
261*9880d681SAndroid Build Coastguard Worker //   2. Handling of serialized operations.
262*9880d681SAndroid Build Coastguard Worker //   3. Handling of the esoteric cases in "Resource-based Instruction Grouping".
263*9880d681SAndroid Build Coastguard Worker //
264*9880d681SAndroid Build Coastguard Worker 
PPCHazardRecognizer970(const ScheduleDAG & DAG)265*9880d681SAndroid Build Coastguard Worker PPCHazardRecognizer970::PPCHazardRecognizer970(const ScheduleDAG &DAG)
266*9880d681SAndroid Build Coastguard Worker     : DAG(DAG) {
267*9880d681SAndroid Build Coastguard Worker   EndDispatchGroup();
268*9880d681SAndroid Build Coastguard Worker }
269*9880d681SAndroid Build Coastguard Worker 
EndDispatchGroup()270*9880d681SAndroid Build Coastguard Worker void PPCHazardRecognizer970::EndDispatchGroup() {
271*9880d681SAndroid Build Coastguard Worker   DEBUG(errs() << "=== Start of dispatch group\n");
272*9880d681SAndroid Build Coastguard Worker   NumIssued = 0;
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker   // Structural hazard info.
275*9880d681SAndroid Build Coastguard Worker   HasCTRSet = false;
276*9880d681SAndroid Build Coastguard Worker   NumStores = 0;
277*9880d681SAndroid Build Coastguard Worker }
278*9880d681SAndroid Build Coastguard Worker 
279*9880d681SAndroid Build Coastguard Worker 
280*9880d681SAndroid Build Coastguard Worker PPCII::PPC970_Unit
GetInstrType(unsigned Opcode,bool & isFirst,bool & isSingle,bool & isCracked,bool & isLoad,bool & isStore)281*9880d681SAndroid Build Coastguard Worker PPCHazardRecognizer970::GetInstrType(unsigned Opcode,
282*9880d681SAndroid Build Coastguard Worker                                      bool &isFirst, bool &isSingle,
283*9880d681SAndroid Build Coastguard Worker                                      bool &isCracked,
284*9880d681SAndroid Build Coastguard Worker                                      bool &isLoad, bool &isStore) {
285*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc &MCID = DAG.TII->get(Opcode);
286*9880d681SAndroid Build Coastguard Worker 
287*9880d681SAndroid Build Coastguard Worker   isLoad  = MCID.mayLoad();
288*9880d681SAndroid Build Coastguard Worker   isStore = MCID.mayStore();
289*9880d681SAndroid Build Coastguard Worker 
290*9880d681SAndroid Build Coastguard Worker   uint64_t TSFlags = MCID.TSFlags;
291*9880d681SAndroid Build Coastguard Worker 
292*9880d681SAndroid Build Coastguard Worker   isFirst   = TSFlags & PPCII::PPC970_First;
293*9880d681SAndroid Build Coastguard Worker   isSingle  = TSFlags & PPCII::PPC970_Single;
294*9880d681SAndroid Build Coastguard Worker   isCracked = TSFlags & PPCII::PPC970_Cracked;
295*9880d681SAndroid Build Coastguard Worker   return (PPCII::PPC970_Unit)(TSFlags & PPCII::PPC970_Mask);
296*9880d681SAndroid Build Coastguard Worker }
297*9880d681SAndroid Build Coastguard Worker 
298*9880d681SAndroid Build Coastguard Worker /// isLoadOfStoredAddress - If we have a load from the previously stored pointer
299*9880d681SAndroid Build Coastguard Worker /// as indicated by StorePtr1/StorePtr2/StoreSize, return true.
300*9880d681SAndroid Build Coastguard Worker bool PPCHazardRecognizer970::
isLoadOfStoredAddress(uint64_t LoadSize,int64_t LoadOffset,const Value * LoadValue) const301*9880d681SAndroid Build Coastguard Worker isLoadOfStoredAddress(uint64_t LoadSize, int64_t LoadOffset,
302*9880d681SAndroid Build Coastguard Worker   const Value *LoadValue) const {
303*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = NumStores; i != e; ++i) {
304*9880d681SAndroid Build Coastguard Worker     // Handle exact and commuted addresses.
305*9880d681SAndroid Build Coastguard Worker     if (LoadValue == StoreValue[i] && LoadOffset == StoreOffset[i])
306*9880d681SAndroid Build Coastguard Worker       return true;
307*9880d681SAndroid Build Coastguard Worker 
308*9880d681SAndroid Build Coastguard Worker     // Okay, we don't have an exact match, if this is an indexed offset, see if
309*9880d681SAndroid Build Coastguard Worker     // we have overlap (which happens during fp->int conversion for example).
310*9880d681SAndroid Build Coastguard Worker     if (StoreValue[i] == LoadValue) {
311*9880d681SAndroid Build Coastguard Worker       // Okay the base pointers match, so we have [c1+r] vs [c2+r].  Check
312*9880d681SAndroid Build Coastguard Worker       // to see if the load and store actually overlap.
313*9880d681SAndroid Build Coastguard Worker       if (StoreOffset[i] < LoadOffset) {
314*9880d681SAndroid Build Coastguard Worker         if (int64_t(StoreOffset[i]+StoreSize[i]) > LoadOffset) return true;
315*9880d681SAndroid Build Coastguard Worker       } else {
316*9880d681SAndroid Build Coastguard Worker         if (int64_t(LoadOffset+LoadSize) > StoreOffset[i]) return true;
317*9880d681SAndroid Build Coastguard Worker       }
318*9880d681SAndroid Build Coastguard Worker     }
319*9880d681SAndroid Build Coastguard Worker   }
320*9880d681SAndroid Build Coastguard Worker   return false;
321*9880d681SAndroid Build Coastguard Worker }
322*9880d681SAndroid Build Coastguard Worker 
323*9880d681SAndroid Build Coastguard Worker /// getHazardType - We return hazard for any non-branch instruction that would
324*9880d681SAndroid Build Coastguard Worker /// terminate the dispatch group.  We turn NoopHazard for any
325*9880d681SAndroid Build Coastguard Worker /// instructions that wouldn't terminate the dispatch group that would cause a
326*9880d681SAndroid Build Coastguard Worker /// pipeline flush.
327*9880d681SAndroid Build Coastguard Worker ScheduleHazardRecognizer::HazardType PPCHazardRecognizer970::
getHazardType(SUnit * SU,int Stalls)328*9880d681SAndroid Build Coastguard Worker getHazardType(SUnit *SU, int Stalls) {
329*9880d681SAndroid Build Coastguard Worker   assert(Stalls == 0 && "PPC hazards don't support scoreboard lookahead");
330*9880d681SAndroid Build Coastguard Worker 
331*9880d681SAndroid Build Coastguard Worker   MachineInstr *MI = SU->getInstr();
332*9880d681SAndroid Build Coastguard Worker 
333*9880d681SAndroid Build Coastguard Worker   if (MI->isDebugValue())
334*9880d681SAndroid Build Coastguard Worker     return NoHazard;
335*9880d681SAndroid Build Coastguard Worker 
336*9880d681SAndroid Build Coastguard Worker   unsigned Opcode = MI->getOpcode();
337*9880d681SAndroid Build Coastguard Worker   bool isFirst, isSingle, isCracked, isLoad, isStore;
338*9880d681SAndroid Build Coastguard Worker   PPCII::PPC970_Unit InstrType =
339*9880d681SAndroid Build Coastguard Worker     GetInstrType(Opcode, isFirst, isSingle, isCracked,
340*9880d681SAndroid Build Coastguard Worker                  isLoad, isStore);
341*9880d681SAndroid Build Coastguard Worker   if (InstrType == PPCII::PPC970_Pseudo) return NoHazard;
342*9880d681SAndroid Build Coastguard Worker 
343*9880d681SAndroid Build Coastguard Worker   // We can only issue a PPC970_First/PPC970_Single instruction (such as
344*9880d681SAndroid Build Coastguard Worker   // crand/mtspr/etc) if this is the first cycle of the dispatch group.
345*9880d681SAndroid Build Coastguard Worker   if (NumIssued != 0 && (isFirst || isSingle))
346*9880d681SAndroid Build Coastguard Worker     return Hazard;
347*9880d681SAndroid Build Coastguard Worker 
348*9880d681SAndroid Build Coastguard Worker   // If this instruction is cracked into two ops by the decoder, we know that
349*9880d681SAndroid Build Coastguard Worker   // it is not a branch and that it cannot issue if 3 other instructions are
350*9880d681SAndroid Build Coastguard Worker   // already in the dispatch group.
351*9880d681SAndroid Build Coastguard Worker   if (isCracked && NumIssued > 2)
352*9880d681SAndroid Build Coastguard Worker     return Hazard;
353*9880d681SAndroid Build Coastguard Worker 
354*9880d681SAndroid Build Coastguard Worker   switch (InstrType) {
355*9880d681SAndroid Build Coastguard Worker   default: llvm_unreachable("Unknown instruction type!");
356*9880d681SAndroid Build Coastguard Worker   case PPCII::PPC970_FXU:
357*9880d681SAndroid Build Coastguard Worker   case PPCII::PPC970_LSU:
358*9880d681SAndroid Build Coastguard Worker   case PPCII::PPC970_FPU:
359*9880d681SAndroid Build Coastguard Worker   case PPCII::PPC970_VALU:
360*9880d681SAndroid Build Coastguard Worker   case PPCII::PPC970_VPERM:
361*9880d681SAndroid Build Coastguard Worker     // We can only issue a branch as the last instruction in a group.
362*9880d681SAndroid Build Coastguard Worker     if (NumIssued == 4) return Hazard;
363*9880d681SAndroid Build Coastguard Worker     break;
364*9880d681SAndroid Build Coastguard Worker   case PPCII::PPC970_CRU:
365*9880d681SAndroid Build Coastguard Worker     // We can only issue a CR instruction in the first two slots.
366*9880d681SAndroid Build Coastguard Worker     if (NumIssued >= 2) return Hazard;
367*9880d681SAndroid Build Coastguard Worker     break;
368*9880d681SAndroid Build Coastguard Worker   case PPCII::PPC970_BRU:
369*9880d681SAndroid Build Coastguard Worker     break;
370*9880d681SAndroid Build Coastguard Worker   }
371*9880d681SAndroid Build Coastguard Worker 
372*9880d681SAndroid Build Coastguard Worker   // Do not allow MTCTR and BCTRL to be in the same dispatch group.
373*9880d681SAndroid Build Coastguard Worker   if (HasCTRSet && Opcode == PPC::BCTRL)
374*9880d681SAndroid Build Coastguard Worker     return NoopHazard;
375*9880d681SAndroid Build Coastguard Worker 
376*9880d681SAndroid Build Coastguard Worker   // If this is a load following a store, make sure it's not to the same or
377*9880d681SAndroid Build Coastguard Worker   // overlapping address.
378*9880d681SAndroid Build Coastguard Worker   if (isLoad && NumStores && !MI->memoperands_empty()) {
379*9880d681SAndroid Build Coastguard Worker     MachineMemOperand *MO = *MI->memoperands_begin();
380*9880d681SAndroid Build Coastguard Worker     if (isLoadOfStoredAddress(MO->getSize(),
381*9880d681SAndroid Build Coastguard Worker                               MO->getOffset(), MO->getValue()))
382*9880d681SAndroid Build Coastguard Worker       return NoopHazard;
383*9880d681SAndroid Build Coastguard Worker   }
384*9880d681SAndroid Build Coastguard Worker 
385*9880d681SAndroid Build Coastguard Worker   return NoHazard;
386*9880d681SAndroid Build Coastguard Worker }
387*9880d681SAndroid Build Coastguard Worker 
EmitInstruction(SUnit * SU)388*9880d681SAndroid Build Coastguard Worker void PPCHazardRecognizer970::EmitInstruction(SUnit *SU) {
389*9880d681SAndroid Build Coastguard Worker   MachineInstr *MI = SU->getInstr();
390*9880d681SAndroid Build Coastguard Worker 
391*9880d681SAndroid Build Coastguard Worker   if (MI->isDebugValue())
392*9880d681SAndroid Build Coastguard Worker     return;
393*9880d681SAndroid Build Coastguard Worker 
394*9880d681SAndroid Build Coastguard Worker   unsigned Opcode = MI->getOpcode();
395*9880d681SAndroid Build Coastguard Worker   bool isFirst, isSingle, isCracked, isLoad, isStore;
396*9880d681SAndroid Build Coastguard Worker   PPCII::PPC970_Unit InstrType =
397*9880d681SAndroid Build Coastguard Worker     GetInstrType(Opcode, isFirst, isSingle, isCracked,
398*9880d681SAndroid Build Coastguard Worker                  isLoad, isStore);
399*9880d681SAndroid Build Coastguard Worker   if (InstrType == PPCII::PPC970_Pseudo) return;
400*9880d681SAndroid Build Coastguard Worker 
401*9880d681SAndroid Build Coastguard Worker   // Update structural hazard information.
402*9880d681SAndroid Build Coastguard Worker   if (Opcode == PPC::MTCTR || Opcode == PPC::MTCTR8) HasCTRSet = true;
403*9880d681SAndroid Build Coastguard Worker 
404*9880d681SAndroid Build Coastguard Worker   // Track the address stored to.
405*9880d681SAndroid Build Coastguard Worker   if (isStore && NumStores < 4 && !MI->memoperands_empty()) {
406*9880d681SAndroid Build Coastguard Worker     MachineMemOperand *MO = *MI->memoperands_begin();
407*9880d681SAndroid Build Coastguard Worker     StoreSize[NumStores] = MO->getSize();
408*9880d681SAndroid Build Coastguard Worker     StoreOffset[NumStores] = MO->getOffset();
409*9880d681SAndroid Build Coastguard Worker     StoreValue[NumStores] = MO->getValue();
410*9880d681SAndroid Build Coastguard Worker     ++NumStores;
411*9880d681SAndroid Build Coastguard Worker   }
412*9880d681SAndroid Build Coastguard Worker 
413*9880d681SAndroid Build Coastguard Worker   if (InstrType == PPCII::PPC970_BRU || isSingle)
414*9880d681SAndroid Build Coastguard Worker     NumIssued = 4;  // Terminate a d-group.
415*9880d681SAndroid Build Coastguard Worker   ++NumIssued;
416*9880d681SAndroid Build Coastguard Worker 
417*9880d681SAndroid Build Coastguard Worker   // If this instruction is cracked into two ops by the decoder, remember that
418*9880d681SAndroid Build Coastguard Worker   // we issued two pieces.
419*9880d681SAndroid Build Coastguard Worker   if (isCracked)
420*9880d681SAndroid Build Coastguard Worker     ++NumIssued;
421*9880d681SAndroid Build Coastguard Worker 
422*9880d681SAndroid Build Coastguard Worker   if (NumIssued == 5)
423*9880d681SAndroid Build Coastguard Worker     EndDispatchGroup();
424*9880d681SAndroid Build Coastguard Worker }
425*9880d681SAndroid Build Coastguard Worker 
AdvanceCycle()426*9880d681SAndroid Build Coastguard Worker void PPCHazardRecognizer970::AdvanceCycle() {
427*9880d681SAndroid Build Coastguard Worker   assert(NumIssued < 5 && "Illegal dispatch group!");
428*9880d681SAndroid Build Coastguard Worker   ++NumIssued;
429*9880d681SAndroid Build Coastguard Worker   if (NumIssued == 5)
430*9880d681SAndroid Build Coastguard Worker     EndDispatchGroup();
431*9880d681SAndroid Build Coastguard Worker }
432*9880d681SAndroid Build Coastguard Worker 
Reset()433*9880d681SAndroid Build Coastguard Worker void PPCHazardRecognizer970::Reset() {
434*9880d681SAndroid Build Coastguard Worker   EndDispatchGroup();
435*9880d681SAndroid Build Coastguard Worker }
436*9880d681SAndroid Build Coastguard Worker 
437