add some comments that describe what we model
[oota-llvm.git] / lib / Target / PowerPC / PPCHazardRecognizers.cpp
1 //===-- PPCHazardRecognizers.cpp - PowerPC Hazard Recognizer Impls --------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Chris Lattner and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements hazard recognizers for scheduling on PowerPC processors.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "sched"
15 #include "PPCHazardRecognizers.h"
16 #include "PPC.h"
17 #include "llvm/Support/Debug.h"
18 #include <iostream>
19 using namespace llvm;
20
21
22 //===----------------------------------------------------------------------===//
23 // PowerPC 970 Hazard Recognizer
24 //
25 // This models the dispatch group formation of the PPC970 processor.  Dispatch
26 // groups are bundles of up to five instructions that can contain up to two ALU
27 // (aka FXU) ops, two FPU ops, two Load/Store ops, one CR op, one VALU op, one
28 // VPERM op, and one BRANCH op.  If the code contains more instructions in a
29 // sequence than the dispatch group can contain (e.g. three loads in a row) the
30 // processor terminates the dispatch group early, wasting execution resources.
31 //
32 // In addition to these restrictions, there are a number of other restrictions:
33 // some instructions, e.g. branches, are required to be the last instruction in
34 // a group.  Additionally, only branches can issue in the 5th (last) slot.
35 //
36 // Finally, there are a number of "structural" hazards on the PPC970.  These
37 // conditions cause large performance penalties due to misprediction, recovery,
38 // and replay logic that has to happen.  These cases include setting a CTR and
39 // branching through it in the same dispatch group, and storing to an address,
40 // then loading from the same address within a dispatch group.  To avoid these
41 // conditions, we insert no-op instructions when appropriate.
42 //
43 // FIXME: This is missing some significant cases:
44 //   0. Handling of instructions that must be the first/last in a group.
45 //   1. Modeling of microcoded instructions.
46 //   2. Handling of cracked instructions.
47 //   3. Handling of serialized operations.
48 //   4. Handling of the esoteric cases in "Resource-based Instruction Grouping",
49 //      e.g. integer divides that only execute in the second slot.
50 //
51
52 void PPCHazardRecognizer970::EndDispatchGroup() {
53   DEBUG(std::cerr << "=== Start of dispatch group\n");
54   // Pipeline units.
55   NumFXU = NumLSU = NumFPU = 0;
56   HasCR = HasVALU = HasVPERM = false;
57   NumIssued = 0;
58   
59   // Structural hazard info.
60   HasCTRSet = false;
61   StorePtr1 = StorePtr2 = SDOperand();
62   StoreSize = 0;
63 }
64
65
66 PPCHazardRecognizer970::PPC970InstrType
67 PPCHazardRecognizer970::GetInstrType(unsigned Opcode) {
68   if (Opcode < ISD::BUILTIN_OP_END)
69     return PseudoInst;
70   Opcode -= ISD::BUILTIN_OP_END;
71   
72   switch (Opcode) {
73   case PPC::FMRSD: return PseudoInst;  // Usually coallesced away.
74   case PPC::BCTRL:
75   case PPC::BL:
76   case PPC::BLA:
77     return BR;
78   case PPC::LFS:
79   case PPC::LWZ:
80     return LSU_LD;
81   case PPC::STFD:
82     return LSU_ST;
83   case PPC::FADDS:
84   case PPC::FCTIWZ:
85     return FPU;
86   }
87   
88   return FXU;
89 }
90
91
92 /// StartBasicBlock - Initiate a new dispatch group.
93 void PPCHazardRecognizer970::StartBasicBlock() {
94   EndDispatchGroup();
95 }
96
97 /// isLoadOfStoredAddress - If we have a load from the previously stored pointer
98 /// as indicated by StorePtr1/StorePtr2/StoreSize, return true.
99 bool PPCHazardRecognizer970::
100 isLoadOfStoredAddress(unsigned LoadSize, SDOperand Ptr1, SDOperand Ptr2) const {
101   // Handle exact and commuted addresses.
102   if (Ptr1 == StorePtr1 && Ptr2 == StorePtr2)
103     return true;
104   if (Ptr2 == StorePtr1 && Ptr1 == StorePtr2)
105     return true;
106   
107   // Okay, we don't have an exact match, if this is an indexed offset, see if we
108   // have overlap (which happens during fp->int conversion for example).
109   if (StorePtr2 == Ptr2) {
110     if (ConstantSDNode *StoreOffset = dyn_cast<ConstantSDNode>(StorePtr1))
111       if (ConstantSDNode *LoadOffset = dyn_cast<ConstantSDNode>(Ptr1)) {
112         // Okay the base pointers match, so we have [c1+r] vs [c2+r].  Check to
113         // see if the load and store actually overlap.
114         int StoreOffs = StoreOffset->getValue();
115         int LoadOffs  = LoadOffset->getValue();
116         if (StoreOffs < LoadOffs) {
117           if (int(StoreOffs+StoreSize) > LoadOffs) return true;
118         } else {
119           if (int(LoadOffs+LoadSize) > StoreOffs) return true;
120         }
121       }
122   }
123   return false;
124 }
125
126 /// getHazardType - We return hazard for any non-branch instruction that would
127 /// terminate terminate the dispatch group.  We turn NoopHazard for any
128 /// instructions that wouldn't terminate the dispatch group that would cause a
129 /// pipeline flush.
130 HazardRecognizer::HazardType PPCHazardRecognizer970::
131 getHazardType(SDNode *Node) {
132   PPC970InstrType InstrType = GetInstrType(Node->getOpcode());
133   if (InstrType == PseudoInst) return NoHazard;  
134   unsigned Opcode = Node->getOpcode()-ISD::BUILTIN_OP_END;
135
136   switch (InstrType) {
137   default: assert(0 && "Unknown instruction type!");
138   case FXU:    if (NumFXU  == 2) return Hazard;
139   case LSU_ST:
140   case LSU_LD: if (NumLSU  == 2) return Hazard;
141   case FPU:    if (NumFPU  == 2) return Hazard;
142   case CR:     if (HasCR) return Hazard;
143   case VALU:   if (HasVALU) return Hazard;
144   case VPERM:  if (HasVPERM) return Hazard;
145   case BR:    break;
146   }
147
148   // We can only issue a branch as the last instruction in a group.
149   if (NumIssued == 4 && InstrType != BR)
150     return Hazard;
151   
152   // Do not allow MTCTR and BCTRL to be in the same dispatch group.
153   if (HasCTRSet && Opcode == PPC::BCTRL)
154     return NoopHazard;
155   
156   // If this is a load following a store, make sure it's not to the same or
157   // overlapping address.
158   if (InstrType == LSU_LD && StoreSize) {
159     unsigned LoadSize;
160     switch (Opcode) {
161     default: assert(0 && "Unknown load!");
162     case PPC::LFS:
163     case PPC::LWZ: LoadSize = 4; break;
164     }
165     
166     if (isLoadOfStoredAddress(LoadSize, 
167                               Node->getOperand(0), Node->getOperand(1)))
168       return NoopHazard;
169   }
170   
171   return NoHazard;
172 }
173
174 void PPCHazardRecognizer970::EmitInstruction(SDNode *Node) {
175   PPC970InstrType InstrType = GetInstrType(Node->getOpcode());
176   if (InstrType == PseudoInst) return;
177   unsigned Opcode = Node->getOpcode()-ISD::BUILTIN_OP_END;
178
179   // Update structural hazard information.
180   if (Opcode == PPC::MTCTR) HasCTRSet = true;
181   
182   // Track the address stored to.
183   if (InstrType == LSU_ST) {
184     StorePtr1 = Node->getOperand(1);
185     StorePtr2 = Node->getOperand(2);
186     switch (Opcode) {
187     default: assert(0 && "Unknown store instruction!");
188     case PPC::STFD: StoreSize = 8; break;
189     }
190   }
191   
192   switch (InstrType) {
193   default: assert(0 && "Unknown instruction type!");
194   case FXU:    ++NumFXU; break;
195   case LSU_LD:
196   case LSU_ST: ++NumLSU; break;
197   case FPU:    ++NumFPU; break;
198   case CR:     HasCR    = true; break;
199   case VALU:   HasVALU  = true; break;
200   case VPERM:  HasVPERM = true; break;
201   case BR:     NumIssued = 4; return;  // ends a d-group.
202   }
203   ++NumIssued;
204   
205   if (NumIssued == 5)
206     EndDispatchGroup();
207 }
208
209 void PPCHazardRecognizer970::AdvanceCycle() {
210   assert(NumIssued < 5 && "Illegal dispatch group!");
211   ++NumIssued;
212   if (NumIssued == 5)
213     EndDispatchGroup();
214 }
215
216 void PPCHazardRecognizer970::EmitNoop() {
217   AdvanceCycle();
218 }