blob: cd02705feeaf65a74a320d822c32763fd8d8fd62 [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//
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
37void 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
51PPCHazardRecognizer970::PPC970InstrType
52PPCHazardRecognizer970::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.
78void 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.
84bool PPCHazardRecognizer970::
85isLoadOfStoredAddress(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.
115HazardRecognizer::HazardType PPCHazardRecognizer970::
116getHazardType(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
159void 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
194void PPCHazardRecognizer970::AdvanceCycle() {
195 assert(NumIssued < 5 && "Illegal dispatch group!");
196 ++NumIssued;
197 if (NumIssued == 5)
198 EndDispatchGroup();
199}
200
201void PPCHazardRecognizer970::EmitNoop() {
202 AdvanceCycle();
203}