diff options
Diffstat (limited to 'lib/Target/PowerPC/PPCHazardRecognizers.cpp')
-rw-r--r-- | lib/Target/PowerPC/PPCHazardRecognizers.cpp | 282 |
1 files changed, 145 insertions, 137 deletions
diff --git a/lib/Target/PowerPC/PPCHazardRecognizers.cpp b/lib/Target/PowerPC/PPCHazardRecognizers.cpp index a88cb12..b52e993 100644 --- a/lib/Target/PowerPC/PPCHazardRecognizers.cpp +++ b/lib/Target/PowerPC/PPCHazardRecognizers.cpp @@ -14,6 +14,7 @@ #define DEBUG_TYPE "sched" #include "PPCHazardRecognizers.h" #include "PPC.h" +#include "PPCInstrInfo.h" #include "llvm/Support/Debug.h" #include <iostream> using namespace llvm; @@ -23,15 +24,14 @@ using namespace llvm; // PowerPC 970 Hazard Recognizer // // This models the dispatch group formation of the PPC970 processor. Dispatch -// groups are bundles of up to five instructions that can contain up to two ALU -// (aka FXU) ops, two FPU ops, two Load/Store ops, one CR op, one VALU op, one -// VPERM op, and one BRANCH op. If the code contains more instructions in a -// sequence than the dispatch group can contain (e.g. three loads in a row) the -// processor terminates the dispatch group early, wasting execution resources. +// groups are bundles of up to five instructions that can contain various mixes +// of instructions. The PPC970 can dispatch a peak of 4 non-branch and one +// branch instruction per-cycle. // -// In addition to these restrictions, there are a number of other restrictions: -// some instructions, e.g. branches, are required to be the last instruction in -// a group. Additionally, only branches can issue in the 5th (last) slot. +// There are a number of restrictions to dispatch group formation: some +// instructions can only be issued in the first slot of a dispatch group, & some +// instructions fill an entire dispatch group. Additionally, only branches can +// issue in the 5th (last) slot. // // Finally, there are a number of "structural" hazards on the PPC970. These // conditions cause large performance penalties due to misprediction, recovery, @@ -41,8 +41,6 @@ using namespace llvm; // conditions, we insert no-op instructions when appropriate. // // FIXME: This is missing some significant cases: -// -1. Handle all of the instruction types in GetInstrType. -// 0. Handling of instructions that must be the first/last in a group. // 1. Modeling of microcoded instructions. // 2. Handling of cracked instructions. // 3. Handling of serialized operations. @@ -50,103 +48,70 @@ using namespace llvm; // e.g. integer divides that only execute in the second slot. // -PPCHazardRecognizer970::PPCHazardRecognizer970() { +PPCHazardRecognizer970::PPCHazardRecognizer970(const TargetInstrInfo &tii) + : TII(tii) { EndDispatchGroup(); } void PPCHazardRecognizer970::EndDispatchGroup() { DEBUG(std::cerr << "=== Start of dispatch group\n"); - // Pipeline units. - NumFXU = NumLSU = NumFPU = 0; - HasCR = HasSPR = HasVALU = HasVPERM = false; NumIssued = 0; // Structural hazard info. HasCTRSet = false; - StorePtr1 = StorePtr2 = SDOperand(); - StoreSize = 0; + NumStores = 0; } -PPCHazardRecognizer970::PPC970InstrType -PPCHazardRecognizer970::GetInstrType(unsigned Opcode) { - if (Opcode < ISD::BUILTIN_OP_END) - return PseudoInst; +PPCII::PPC970_Unit +PPCHazardRecognizer970::GetInstrType(unsigned Opcode, + bool &isFirst, bool &isSingle, + bool &isLoad, bool &isStore){ + if (Opcode < ISD::BUILTIN_OP_END) { + isFirst = isSingle = isLoad = isStore = false; + return PPCII::PPC970_Pseudo; + } Opcode -= ISD::BUILTIN_OP_END; - switch (Opcode) { - case PPC::FMRSD: return PseudoInst; // Usually coallesced away. - case PPC::BCTRL: - case PPC::BL: - case PPC::BLA: - case PPC::BLR: - return BR; - case PPC::MCRF: - case PPC::MFCR: - case PPC::MFOCRF: - return CR; - case PPC::MFLR: - case PPC::MFCTR: - case PPC::MTLR: - case PPC::MTCTR: - return SPR; - case PPC::LFS: - case PPC::LFD: - case PPC::LWZ: - case PPC::LFSX: - case PPC::LWZX: - case PPC::LBZ: - case PPC::LHA: - case PPC::LHZ: - case PPC::LWZU: - return LSU_LD; - case PPC::STFS: - case PPC::STFD: - case PPC::STW: - case PPC::STB: - case PPC::STH: - case PPC::STWU: - return LSU_ST; - case PPC::DIVW: - case PPC::DIVWU: - case PPC::DIVD: - case PPC::DIVDU: - return FXU_FIRST; - case PPC::FADDS: - case PPC::FCTIWZ: - case PPC::FRSP: - case PPC::FSUB: - return FPU; - } + const TargetInstrDescriptor &TID = TII.get(Opcode); + + isLoad = TID.Flags & M_LOAD_FLAG; + isStore = TID.Flags & M_STORE_FLAG; - return FXU; + unsigned TSFlags = TID.TSFlags; + + isFirst = TSFlags & PPCII::PPC970_First; + isSingle = TSFlags & PPCII::PPC970_Single; + return (PPCII::PPC970_Unit)(TSFlags & PPCII::PPC970_Mask); } /// isLoadOfStoredAddress - If we have a load from the previously stored pointer /// as indicated by StorePtr1/StorePtr2/StoreSize, return true. bool PPCHazardRecognizer970:: isLoadOfStoredAddress(unsigned LoadSize, SDOperand Ptr1, SDOperand Ptr2) const { - // Handle exact and commuted addresses. - if (Ptr1 == StorePtr1 && Ptr2 == StorePtr2) - return true; - if (Ptr2 == StorePtr1 && Ptr1 == StorePtr2) - return true; - - // Okay, we don't have an exact match, if this is an indexed offset, see if we - // have overlap (which happens during fp->int conversion for example). - if (StorePtr2 == Ptr2) { - if (ConstantSDNode *StoreOffset = dyn_cast<ConstantSDNode>(StorePtr1)) - if (ConstantSDNode *LoadOffset = dyn_cast<ConstantSDNode>(Ptr1)) { - // Okay the base pointers match, so we have [c1+r] vs [c2+r]. Check to - // see if the load and store actually overlap. - int StoreOffs = StoreOffset->getValue(); - int LoadOffs = LoadOffset->getValue(); - if (StoreOffs < LoadOffs) { - if (int(StoreOffs+StoreSize) > LoadOffs) return true; - } else { - if (int(LoadOffs+LoadSize) > StoreOffs) return true; + for (unsigned i = 0, e = NumStores; i != e; ++i) { + // Handle exact and commuted addresses. + if (Ptr1 == StorePtr1[i] && Ptr2 == StorePtr2[i]) + return true; + if (Ptr2 == StorePtr1[i] && Ptr1 == StorePtr2[i]) + return true; + + // Okay, we don't have an exact match, if this is an indexed offset, see if + // we have overlap (which happens during fp->int conversion for example). + if (StorePtr2[i] == Ptr2) { + if (ConstantSDNode *StoreOffset = dyn_cast<ConstantSDNode>(StorePtr1[i])) + if (ConstantSDNode *LoadOffset = dyn_cast<ConstantSDNode>(Ptr1)) { + // Okay the base pointers match, so we have [c1+r] vs [c2+r]. Check + // to see if the load and store actually overlap. + int StoreOffs = StoreOffset->getValue(); + int LoadOffs = LoadOffset->getValue(); + if (StoreOffs < LoadOffs) { + if (int(StoreOffs+StoreSize) > LoadOffs) return true; + } else { + if (int(LoadOffs+LoadSize) > StoreOffs) return true; + } } - } + } } return false; } @@ -157,53 +122,76 @@ isLoadOfStoredAddress(unsigned LoadSize, SDOperand Ptr1, SDOperand Ptr2) const { /// pipeline flush. HazardRecognizer::HazardType PPCHazardRecognizer970:: getHazardType(SDNode *Node) { - PPC970InstrType InstrType = GetInstrType(Node->getOpcode()); - if (InstrType == PseudoInst) return NoHazard; + bool isFirst, isSingle, isLoad, isStore; + PPCII::PPC970_Unit InstrType = + GetInstrType(Node->getOpcode(), isFirst, isSingle, isLoad, isStore); + if (InstrType == PPCII::PPC970_Pseudo) return NoHazard; unsigned Opcode = Node->getOpcode()-ISD::BUILTIN_OP_END; + // We can only issue a PPC970_First/PPC970_Single instruction (such as + // crand/mtspr/etc) if this is the first cycle of the dispatch group. + if (NumIssued != 0 && (isFirst || isSingle) ) + return Hazard; + switch (InstrType) { default: assert(0 && "Unknown instruction type!"); - case FXU: - case FXU_FIRST: if (NumFXU == 2) return Hazard; - case LSU_ST: - case LSU_LD: if (NumLSU == 2) return Hazard; - case FPU: if (NumFPU == 2) return Hazard; - case CR: if (HasCR) return Hazard; - case SPR: if (HasSPR) return Hazard; - case VALU: if (HasVALU) return Hazard; - case VPERM: if (HasVPERM) return Hazard; - case BR: break; + case PPCII::PPC970_FXU: + case PPCII::PPC970_LSU: + case PPCII::PPC970_FPU: + case PPCII::PPC970_VALU: + case PPCII::PPC970_VPERM: + // We can only issue a branch as the last instruction in a group. + if (NumIssued == 4) return Hazard; + break; + case PPCII::PPC970_CRU: + // We can only issue a CR instruction in the first two slots. + if (NumIssued >= 2) return Hazard; + break; + case PPCII::PPC970_BRU: + break; } - - // We can only issue a CR or SPR instruction, or an FXU instruction that needs - // to lead a dispatch group as the first instruction in the group. - if (NumIssued != 0 && - (InstrType == CR || InstrType == SPR || InstrType == FXU_FIRST)) - return Hazard; - - // We can only issue a branch as the last instruction in a group. - if (NumIssued == 4 && InstrType != BR) - return Hazard; - + // Do not allow MTCTR and BCTRL to be in the same dispatch group. if (HasCTRSet && Opcode == PPC::BCTRL) return NoopHazard; // If this is a load following a store, make sure it's not to the same or // overlapping address. - if (InstrType == LSU_LD && StoreSize) { + if (isLoad && StoreSize) { unsigned LoadSize; switch (Opcode) { default: assert(0 && "Unknown load!"); - case PPC::LBZ: LoadSize = 1; break; + case PPC::LBZ: + case PPC::LBZX: + case PPC::LVEBX: + LoadSize = 1; + break; case PPC::LHA: - case PPC::LHZ: LoadSize = 2; break; - case PPC::LWZU: - case PPC::LFSX: + case PPC::LHAX: + case PPC::LHZ: + case PPC::LHZX: + case PPC::LVEHX: + LoadSize = 2; + break; case PPC::LFS: + case PPC::LFSX: + case PPC::LWZ: case PPC::LWZX: - case PPC::LWZ: LoadSize = 4; break; - case PPC::LFD: LoadSize = 8; break; + case PPC::LWZU: + case PPC::LWA: + case PPC::LWAX: + case PPC::LVEWX: + LoadSize = 4; + break; + case PPC::LFD: + case PPC::LFDX: + case PPC::LD: + case PPC::LDX: + LoadSize = 8; + break; + case PPC::LVX: + LoadSize = 16; + break; } if (isLoadOfStoredAddress(LoadSize, @@ -215,41 +203,61 @@ getHazardType(SDNode *Node) { } void PPCHazardRecognizer970::EmitInstruction(SDNode *Node) { - PPC970InstrType InstrType = GetInstrType(Node->getOpcode()); - if (InstrType == PseudoInst) return; + bool isFirst, isSingle, isLoad, isStore; + PPCII::PPC970_Unit InstrType = + GetInstrType(Node->getOpcode(), isFirst, isSingle, isLoad, isStore); + if (InstrType == PPCII::PPC970_Pseudo) return; unsigned Opcode = Node->getOpcode()-ISD::BUILTIN_OP_END; // Update structural hazard information. if (Opcode == PPC::MTCTR) HasCTRSet = true; // Track the address stored to. - if (InstrType == LSU_ST) { - StorePtr1 = Node->getOperand(1); - StorePtr2 = Node->getOperand(2); + if (isStore) { + unsigned ThisStoreSize; switch (Opcode) { default: assert(0 && "Unknown store instruction!"); - case PPC::STB: StoreSize = 1; break; - case PPC::STH: StoreSize = 2; break; + case PPC::STBX: + case PPC::STB: + case PPC::STVEBX: + ThisStoreSize = 1; + break; + case PPC::STHX: + case PPC::STH: + case PPC::STVEHX: + ThisStoreSize = 2; + break; case PPC::STFS: + case PPC::STFSX: case PPC::STWU: - case PPC::STW: StoreSize = 4; break; - case PPC::STFD: StoreSize = 8; break; + case PPC::STWX: + case PPC::STWUX: + case PPC::STW: + case PPC::STVEWX: + case PPC::STFIWX: + ThisStoreSize = 4; + break; + case PPC::STD: + case PPC::STDU: + case PPC::STFD: + case PPC::STFDX: + case PPC::STDX: + case PPC::STDUX: + ThisStoreSize = 8; + break; + case PPC::STVX: + ThisStoreSize = 16; + break; } + + StoreSize[NumStores] = ThisStoreSize; + StorePtr1[NumStores] = Node->getOperand(1); + StorePtr2[NumStores] = Node->getOperand(2); + ++NumStores; } - switch (InstrType) { - default: assert(0 && "Unknown instruction type!"); - case FXU: - case FXU_FIRST: ++NumFXU; break; - case LSU_LD: - case LSU_ST: ++NumLSU; break; - case FPU: ++NumFPU; break; - case CR: HasCR = true; break; - case SPR: HasSPR = true; break; - case VALU: HasVALU = true; break; - case VPERM: HasVPERM = true; break; - case BR: NumIssued = 4; return; // ends a d-group. - } + if (InstrType == PPCII::PPC970_BRU || isSingle) + NumIssued = 4; // Terminate a d-group. ++NumIssued; if (NumIssued == 5) |