blob: 1b1559546b2c5db77b3afbb153851176eef70564 [file] [log] [blame]
Chris Lattnerc6644182006-03-07 06:32:48 +00001//===-- 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>
19using namespace llvm;
20
21
22//===----------------------------------------------------------------------===//
23// PowerPC 970 Hazard Recognizer
24//
Chris Lattner7ce64852006-03-07 06:44:19 +000025// 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//
Chris Lattnerc6644182006-03-07 06:32:48 +000043// 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//
Chris Lattnerc6644182006-03-07 06:32:48 +000051
52void 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
66PPCHazardRecognizer970::PPC970InstrType
67PPCHazardRecognizer970::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.
93void 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.
99bool PPCHazardRecognizer970::
100isLoadOfStoredAddress(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.
130HazardRecognizer::HazardType PPCHazardRecognizer970::
131getHazardType(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
174void 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
209void PPCHazardRecognizer970::AdvanceCycle() {
210 assert(NumIssued < 5 && "Illegal dispatch group!");
211 ++NumIssued;
212 if (NumIssued == 5)
213 EndDispatchGroup();
214}
215
216void PPCHazardRecognizer970::EmitNoop() {
217 AdvanceCycle();
218}