1155192Srwatson//===-- PPCHazardRecognizers.cpp - PowerPC Hazard Recognizer Impls --------===//
2180701Srwatson//
3155192Srwatson//                     The LLVM Compiler Infrastructure
4155192Srwatson//
5155192Srwatson// This file is distributed under the University of Illinois Open Source
6155192Srwatson// License. See LICENSE.TXT for details.
7155192Srwatson//
8155192Srwatson//===----------------------------------------------------------------------===//
9155192Srwatson//
10155192Srwatson// This file implements hazard recognizers for scheduling on PowerPC processors.
11155192Srwatson//
12155192Srwatson//===----------------------------------------------------------------------===//
13180701Srwatson
14155192Srwatson#define DEBUG_TYPE "pre-RA-sched"
15155192Srwatson#include "PPCHazardRecognizers.h"
16155192Srwatson#include "PPC.h"
17155192Srwatson#include "PPCInstrInfo.h"
18155192Srwatson#include "llvm/CodeGen/ScheduleDAG.h"
19155192Srwatson#include "llvm/Support/Debug.h"
20155192Srwatson#include "llvm/Support/ErrorHandling.h"
21155192Srwatson#include "llvm/Support/raw_ostream.h"
22155192Srwatsonusing namespace llvm;
23155192Srwatson
24155192Srwatson//===----------------------------------------------------------------------===//
25155192Srwatson// PowerPC Scoreboard Hazard Recognizer
26155192Srwatsonvoid PPCScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) {
27155192Srwatson  const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
28155192Srwatson  if (!MCID)
29155192Srwatson    // This is a PPC pseudo-instruction.
30178186Srwatson    return;
31178186Srwatson
32178186Srwatson  ScoreboardHazardRecognizer::EmitInstruction(SU);
33155192Srwatson}
34155192Srwatson
35155192SrwatsonScheduleHazardRecognizer::HazardType
36155192SrwatsonPPCScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
37155192Srwatson  return ScoreboardHazardRecognizer::getHazardType(SU, Stalls);
38155192Srwatson}
39155192Srwatson
40160136Swsalamonvoid PPCScoreboardHazardRecognizer::AdvanceCycle() {
41155192Srwatson  ScoreboardHazardRecognizer::AdvanceCycle();
42155192Srwatson}
43155192Srwatson
44155192Srwatsonvoid PPCScoreboardHazardRecognizer::Reset() {
45155192Srwatson  ScoreboardHazardRecognizer::Reset();
46155192Srwatson}
47155192Srwatson
48155192Srwatson//===----------------------------------------------------------------------===//
49155192Srwatson// PowerPC 970 Hazard Recognizer
50155192Srwatson//
51155192Srwatson// This models the dispatch group formation of the PPC970 processor.  Dispatch
52155192Srwatson// groups are bundles of up to five instructions that can contain various mixes
53155192Srwatson// of instructions.  The PPC970 can dispatch a peak of 4 non-branch and one
54155192Srwatson// branch instruction per-cycle.
55155192Srwatson//
56155192Srwatson// There are a number of restrictions to dispatch group formation: some
57155192Srwatson// instructions can only be issued in the first slot of a dispatch group, & some
58155192Srwatson// instructions fill an entire dispatch group.  Additionally, only branches can
59155192Srwatson// issue in the 5th (last) slot.
60155192Srwatson//
61155192Srwatson// Finally, there are a number of "structural" hazards on the PPC970.  These
62155192Srwatson// conditions cause large performance penalties due to misprediction, recovery,
63155192Srwatson// and replay logic that has to happen.  These cases include setting a CTR and
64155192Srwatson// branching through it in the same dispatch group, and storing to an address,
65155192Srwatson// then loading from the same address within a dispatch group.  To avoid these
66155192Srwatson// conditions, we insert no-op instructions when appropriate.
67155192Srwatson//
68155192Srwatson// FIXME: This is missing some significant cases:
69155192Srwatson//   1. Modeling of microcoded instructions.
70155192Srwatson//   2. Handling of serialized operations.
71155192Srwatson//   3. Handling of the esoteric cases in "Resource-based Instruction Grouping".
72155192Srwatson//
73156889Srwatson
74156889SrwatsonPPCHazardRecognizer970::PPCHazardRecognizer970(const TargetMachine &TM)
75156889Srwatson  : TM(TM) {
76180706Srwatson  EndDispatchGroup();
77156889Srwatson}
78156889Srwatson
79155192Srwatsonvoid PPCHazardRecognizer970::EndDispatchGroup() {
80156889Srwatson  DEBUG(errs() << "=== Start of dispatch group\n");
81155192Srwatson  NumIssued = 0;
82156889Srwatson
83155192Srwatson  // Structural hazard info.
84162466Srwatson  HasCTRSet = false;
85155192Srwatson  NumStores = 0;
86155192Srwatson}
87155192Srwatson
88155192Srwatson
89155192SrwatsonPPCII::PPC970_Unit
90155192SrwatsonPPCHazardRecognizer970::GetInstrType(unsigned Opcode,
91155192Srwatson                                     bool &isFirst, bool &isSingle,
92155192Srwatson                                     bool &isCracked,
93155192Srwatson                                     bool &isLoad, bool &isStore) {
94156889Srwatson  const MCInstrDesc &MCID = TM.getInstrInfo()->get(Opcode);
95155192Srwatson
96155192Srwatson  isLoad  = MCID.mayLoad();
97155192Srwatson  isStore = MCID.mayStore();
98155192Srwatson
99155192Srwatson  uint64_t TSFlags = MCID.TSFlags;
100155192Srwatson
101155192Srwatson  isFirst   = TSFlags & PPCII::PPC970_First;
102155192Srwatson  isSingle  = TSFlags & PPCII::PPC970_Single;
103155192Srwatson  isCracked = TSFlags & PPCII::PPC970_Cracked;
104155192Srwatson  return (PPCII::PPC970_Unit)(TSFlags & PPCII::PPC970_Mask);
105155192Srwatson}
106155192Srwatson
107155192Srwatson/// isLoadOfStoredAddress - If we have a load from the previously stored pointer
108155192Srwatson/// as indicated by StorePtr1/StorePtr2/StoreSize, return true.
109155192Srwatsonbool PPCHazardRecognizer970::
110155192SrwatsonisLoadOfStoredAddress(uint64_t LoadSize, int64_t LoadOffset,
111155192Srwatson  const Value *LoadValue) const {
112155192Srwatson  for (unsigned i = 0, e = NumStores; i != e; ++i) {
113155192Srwatson    // Handle exact and commuted addresses.
114155192Srwatson    if (LoadValue == StoreValue[i] && LoadOffset == StoreOffset[i])
115155192Srwatson      return true;
116156889Srwatson
117161635Srwatson    // Okay, we don't have an exact match, if this is an indexed offset, see if
118162466Srwatson    // we have overlap (which happens during fp->int conversion for example).
119170196Srwatson    if (StoreValue[i] == LoadValue) {
120162466Srwatson      // Okay the base pointers match, so we have [c1+r] vs [c2+r].  Check
121162466Srwatson      // to see if the load and store actually overlap.
122162466Srwatson      if (StoreOffset[i] < LoadOffset) {
123162466Srwatson        if (int64_t(StoreOffset[i]+StoreSize[i]) > LoadOffset) return true;
124155192Srwatson      } else {
125162466Srwatson        if (int64_t(LoadOffset+LoadSize) > StoreOffset[i]) return true;
126162466Srwatson      }
127155192Srwatson    }
128162466Srwatson  }
129162466Srwatson  return false;
130162466Srwatson}
131162466Srwatson
132162466Srwatson/// getHazardType - We return hazard for any non-branch instruction that would
133155192Srwatson/// terminate the dispatch group.  We turn NoopHazard for any
134155192Srwatson/// instructions that wouldn't terminate the dispatch group that would cause a
135155192Srwatson/// pipeline flush.
136155192SrwatsonScheduleHazardRecognizer::HazardType PPCHazardRecognizer970::
137156889SrwatsongetHazardType(SUnit *SU, int Stalls) {
138156889Srwatson  assert(Stalls == 0 && "PPC hazards don't support scoreboard lookahead");
139155192Srwatson
140155192Srwatson  MachineInstr *MI = SU->getInstr();
141155192Srwatson
142155192Srwatson  if (MI->isDebugValue())
143155192Srwatson    return NoHazard;
144155192Srwatson
145156889Srwatson  unsigned Opcode = MI->getOpcode();
146155192Srwatson  bool isFirst, isSingle, isCracked, isLoad, isStore;
147155192Srwatson  PPCII::PPC970_Unit InstrType =
148155192Srwatson    GetInstrType(Opcode, isFirst, isSingle, isCracked,
149155192Srwatson                 isLoad, isStore);
150156889Srwatson  if (InstrType == PPCII::PPC970_Pseudo) return NoHazard;
151155192Srwatson
152155192Srwatson  // We can only issue a PPC970_First/PPC970_Single instruction (such as
153156889Srwatson  // crand/mtspr/etc) if this is the first cycle of the dispatch group.
154155192Srwatson  if (NumIssued != 0 && (isFirst || isSingle))
155155192Srwatson    return Hazard;
156155192Srwatson
157155192Srwatson  // If this instruction is cracked into two ops by the decoder, we know that
158155192Srwatson  // it is not a branch and that it cannot issue if 3 other instructions are
159170196Srwatson  // already in the dispatch group.
160180704Srwatson  if (isCracked && NumIssued > 2)
161155192Srwatson    return Hazard;
162155192Srwatson
163155192Srwatson  switch (InstrType) {
164155192Srwatson  default: llvm_unreachable("Unknown instruction type!");
165180708Srwatson  case PPCII::PPC970_FXU:
166155192Srwatson  case PPCII::PPC970_LSU:
167155192Srwatson  case PPCII::PPC970_FPU:
168155192Srwatson  case PPCII::PPC970_VALU:
169155192Srwatson  case PPCII::PPC970_VPERM:
170155192Srwatson    // We can only issue a branch as the last instruction in a group.
171155192Srwatson    if (NumIssued == 4) return Hazard;
172180708Srwatson    break;
173155192Srwatson  case PPCII::PPC970_CRU:
174155192Srwatson    // We can only issue a CR instruction in the first two slots.
175155192Srwatson    if (NumIssued >= 2) return Hazard;
176155192Srwatson    break;
177155192Srwatson  case PPCII::PPC970_BRU:
178155192Srwatson    break;
179180708Srwatson  }
180180709Srwatson
181155192Srwatson  // Do not allow MTCTR and BCTRL to be in the same dispatch group.
182155192Srwatson  if (HasCTRSet && Opcode == PPC::BCTRL)
183155192Srwatson    return NoopHazard;
184155192Srwatson
185155192Srwatson  // If this is a load following a store, make sure it's not to the same or
186180708Srwatson  // overlapping address.
187180709Srwatson  if (isLoad && NumStores && !MI->memoperands_empty()) {
188155192Srwatson    MachineMemOperand *MO = *MI->memoperands_begin();
189155192Srwatson    if (isLoadOfStoredAddress(MO->getSize(),
190180709Srwatson                              MO->getOffset(), MO->getValue()))
191155192Srwatson      return NoopHazard;
192155192Srwatson  }
193155192Srwatson
194155192Srwatson  return NoHazard;
195155192Srwatson}
196180708Srwatson
197180709Srwatsonvoid PPCHazardRecognizer970::EmitInstruction(SUnit *SU) {
198155192Srwatson  MachineInstr *MI = SU->getInstr();
199155192Srwatson
200155192Srwatson  if (MI->isDebugValue())
201155192Srwatson    return;
202155192Srwatson
203180711Srwatson  unsigned Opcode = MI->getOpcode();
204155192Srwatson  bool isFirst, isSingle, isCracked, isLoad, isStore;
205155192Srwatson  PPCII::PPC970_Unit InstrType =
206155192Srwatson    GetInstrType(Opcode, isFirst, isSingle, isCracked,
207155192Srwatson                 isLoad, isStore);
208155192Srwatson  if (InstrType == PPCII::PPC970_Pseudo) return;
209155192Srwatson
210155192Srwatson  // Update structural hazard information.
211155192Srwatson  if (Opcode == PPC::MTCTR || Opcode == PPC::MTCTR8) HasCTRSet = true;
212155192Srwatson
213156889Srwatson  // Track the address stored to.
214156889Srwatson  if (isStore && NumStores < 4 && !MI->memoperands_empty()) {
215155192Srwatson    MachineMemOperand *MO = *MI->memoperands_begin();
216155192Srwatson    StoreSize[NumStores] = MO->getSize();
217155192Srwatson    StoreOffset[NumStores] = MO->getOffset();
218155192Srwatson    StoreValue[NumStores] = MO->getValue();
219155192Srwatson    ++NumStores;
220180708Srwatson  }
221159277Srwatson
222159277Srwatson  if (InstrType == PPCII::PPC970_BRU || isSingle)
223172915Scsjp    NumIssued = 4;  // Terminate a d-group.
224159277Srwatson  ++NumIssued;
225159277Srwatson
226159277Srwatson  // If this instruction is cracked into two ops by the decoder, remember that
227172915Scsjp  // we issued two pieces.
228159277Srwatson  if (isCracked)
229159277Srwatson    ++NumIssued;
230159277Srwatson
231159277Srwatson  if (NumIssued == 5)
232155192Srwatson    EndDispatchGroup();
233180712Srwatson}
234155192Srwatson
235180711Srwatsonvoid PPCHazardRecognizer970::AdvanceCycle() {
236160136Swsalamon  assert(NumIssued < 5 && "Illegal dispatch group!");
237160136Swsalamon  ++NumIssued;
238160136Swsalamon  if (NumIssued == 5)
239160136Swsalamon    EndDispatchGroup();
240160136Swsalamon}
241160136Swsalamon
242160136Swsalamonvoid PPCHazardRecognizer970::Reset() {
243160136Swsalamon  EndDispatchGroup();
244160136Swsalamon}
245160136Swsalamon
246160136Swsalamon