Implement a very very simple hazard recognizer for LSU rejects and ctr set/read
[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 // FIXME: This is missing some significant cases:
26 //   0. Handling of instructions that must be the first/last in a group.
27 //   1. Modeling of microcoded instructions.
28 //   2. Handling of cracked instructions.
29 //   3. Handling of serialized operations.
30 //   4. Handling of the esoteric cases in "Resource-based Instruction Grouping",
31 //      e.g. integer divides that only execute in the second slot.
32 //
33 // Note: on the PPC970, logical CR operations are more expensive in their three
34 // address form: ops that read/write the same register are half as expensive as
35 //
36
37 void PPCHazardRecognizer970::EndDispatchGroup() {
38   DEBUG(std::cerr << "=== Start of dispatch group\n");
39   // Pipeline units.
40   NumFXU = NumLSU = NumFPU = 0;
41   HasCR = HasVALU = HasVPERM = false;
42   NumIssued = 0;
43   
44   // Structural hazard info.
45   HasCTRSet = false;
46   StorePtr1 = StorePtr2 = SDOperand();
47   StoreSize = 0;
48 }
49
50
51 PPCHazardRecognizer970::PPC970InstrType
52 PPCHazardRecognizer970::GetInstrType(unsigned Opcode) {
53   if (Opcode < ISD::BUILTIN_OP_END)
54     return PseudoInst;
55   Opcode -= ISD::BUILTIN_OP_END;
56   
57   switch (Opcode) {
58   case PPC::FMRSD: return PseudoInst;  // Usually coallesced away.
59   case PPC::BCTRL:
60   case PPC::BL:
61   case PPC::BLA:
62     return BR;
63   case PPC::LFS:
64   case PPC::LWZ:
65     return LSU_LD;
66   case PPC::STFD:
67     return LSU_ST;
68   case PPC::FADDS:
69   case PPC::FCTIWZ:
70     return FPU;
71   }
72   
73   return FXU;
74 }
75
76
77 /// StartBasicBlock - Initiate a new dispatch group.
78 void PPCHazardRecognizer970::StartBasicBlock() {
79   EndDispatchGroup();
80 }
81
82 /// isLoadOfStoredAddress - If we have a load from the previously stored pointer
83 /// as indicated by StorePtr1/StorePtr2/StoreSize, return true.
84 bool PPCHazardRecognizer970::
85 isLoadOfStoredAddress(unsigned LoadSize, SDOperand Ptr1, SDOperand Ptr2) const {
86   // Handle exact and commuted addresses.
87   if (Ptr1 == StorePtr1 && Ptr2 == StorePtr2)
88     return true;
89   if (Ptr2 == StorePtr1 && Ptr1 == StorePtr2)
90     return true;
91   
92   // Okay, we don't have an exact match, if this is an indexed offset, see if we
93   // have overlap (which happens during fp->int conversion for example).
94   if (StorePtr2 == Ptr2) {
95     if (ConstantSDNode *StoreOffset = dyn_cast<ConstantSDNode>(StorePtr1))
96       if (ConstantSDNode *LoadOffset = dyn_cast<ConstantSDNode>(Ptr1)) {
97         // Okay the base pointers match, so we have [c1+r] vs [c2+r].  Check to
98         // see if the load and store actually overlap.
99         int StoreOffs = StoreOffset->getValue();
100         int LoadOffs  = LoadOffset->getValue();
101         if (StoreOffs < LoadOffs) {
102           if (int(StoreOffs+StoreSize) > LoadOffs) return true;
103         } else {
104           if (int(LoadOffs+LoadSize) > StoreOffs) return true;
105         }
106       }
107   }
108   return false;
109 }
110
111 /// getHazardType - We return hazard for any non-branch instruction that would
112 /// terminate terminate the dispatch group.  We turn NoopHazard for any
113 /// instructions that wouldn't terminate the dispatch group that would cause a
114 /// pipeline flush.
115 HazardRecognizer::HazardType PPCHazardRecognizer970::
116 getHazardType(SDNode *Node) {
117   PPC970InstrType InstrType = GetInstrType(Node->getOpcode());
118   if (InstrType == PseudoInst) return NoHazard;  
119   unsigned Opcode = Node->getOpcode()-ISD::BUILTIN_OP_END;
120
121   switch (InstrType) {
122   default: assert(0 && "Unknown instruction type!");
123   case FXU:    if (NumFXU  == 2) return Hazard;
124   case LSU_ST:
125   case LSU_LD: if (NumLSU  == 2) return Hazard;
126   case FPU:    if (NumFPU  == 2) return Hazard;
127   case CR:     if (HasCR) return Hazard;
128   case VALU:   if (HasVALU) return Hazard;
129   case VPERM:  if (HasVPERM) return Hazard;
130   case BR:    break;
131   }
132
133   // We can only issue a branch as the last instruction in a group.
134   if (NumIssued == 4 && InstrType != BR)
135     return Hazard;
136   
137   // Do not allow MTCTR and BCTRL to be in the same dispatch group.
138   if (HasCTRSet && Opcode == PPC::BCTRL)
139     return NoopHazard;
140   
141   // If this is a load following a store, make sure it's not to the same or
142   // overlapping address.
143   if (InstrType == LSU_LD && StoreSize) {
144     unsigned LoadSize;
145     switch (Opcode) {
146     default: assert(0 && "Unknown load!");
147     case PPC::LFS:
148     case PPC::LWZ: LoadSize = 4; break;
149     }
150     
151     if (isLoadOfStoredAddress(LoadSize, 
152                               Node->getOperand(0), Node->getOperand(1)))
153       return NoopHazard;
154   }
155   
156   return NoHazard;
157 }
158
159 void PPCHazardRecognizer970::EmitInstruction(SDNode *Node) {
160   PPC970InstrType InstrType = GetInstrType(Node->getOpcode());
161   if (InstrType == PseudoInst) return;
162   unsigned Opcode = Node->getOpcode()-ISD::BUILTIN_OP_END;
163
164   // Update structural hazard information.
165   if (Opcode == PPC::MTCTR) HasCTRSet = true;
166   
167   // Track the address stored to.
168   if (InstrType == LSU_ST) {
169     StorePtr1 = Node->getOperand(1);
170     StorePtr2 = Node->getOperand(2);
171     switch (Opcode) {
172     default: assert(0 && "Unknown store instruction!");
173     case PPC::STFD: StoreSize = 8; break;
174     }
175   }
176   
177   switch (InstrType) {
178   default: assert(0 && "Unknown instruction type!");
179   case FXU:    ++NumFXU; break;
180   case LSU_LD:
181   case LSU_ST: ++NumLSU; break;
182   case FPU:    ++NumFPU; break;
183   case CR:     HasCR    = true; break;
184   case VALU:   HasVALU  = true; break;
185   case VPERM:  HasVPERM = true; break;
186   case BR:     NumIssued = 4; return;  // ends a d-group.
187   }
188   ++NumIssued;
189   
190   if (NumIssued == 5)
191     EndDispatchGroup();
192 }
193
194 void PPCHazardRecognizer970::AdvanceCycle() {
195   assert(NumIssued < 5 && "Illegal dispatch group!");
196   ++NumIssued;
197   if (NumIssued == 5)
198     EndDispatchGroup();
199 }
200
201 void PPCHazardRecognizer970::EmitNoop() {
202   AdvanceCycle();
203 }