From: Chris Lattner Date: Tue, 7 Mar 2006 06:32:48 +0000 (+0000) Subject: Implement a very very simple hazard recognizer for LSU rejects and ctr set/read X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=c6644188208d4aee9a9d6c428710ec1f69837944;p=oota-llvm.git Implement a very very simple hazard recognizer for LSU rejects and ctr set/read flushes git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26587 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/PowerPC/PPCHazardRecognizers.cpp b/lib/Target/PowerPC/PPCHazardRecognizers.cpp new file mode 100644 index 00000000000..cd02705feea --- /dev/null +++ b/lib/Target/PowerPC/PPCHazardRecognizers.cpp @@ -0,0 +1,203 @@ +//===-- PPCHazardRecognizers.cpp - PowerPC Hazard Recognizer Impls --------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements hazard recognizers for scheduling on PowerPC processors. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "sched" +#include "PPCHazardRecognizers.h" +#include "PPC.h" +#include "llvm/Support/Debug.h" +#include +using namespace llvm; + + +//===----------------------------------------------------------------------===// +// PowerPC 970 Hazard Recognizer +// +// FIXME: This is missing some significant cases: +// 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. +// 4. Handling of the esoteric cases in "Resource-based Instruction Grouping", +// e.g. integer divides that only execute in the second slot. +// +// Note: on the PPC970, logical CR operations are more expensive in their three +// address form: ops that read/write the same register are half as expensive as +// + +void PPCHazardRecognizer970::EndDispatchGroup() { + DEBUG(std::cerr << "=== Start of dispatch group\n"); + // Pipeline units. + NumFXU = NumLSU = NumFPU = 0; + HasCR = HasVALU = HasVPERM = false; + NumIssued = 0; + + // Structural hazard info. + HasCTRSet = false; + StorePtr1 = StorePtr2 = SDOperand(); + StoreSize = 0; +} + + +PPCHazardRecognizer970::PPC970InstrType +PPCHazardRecognizer970::GetInstrType(unsigned Opcode) { + if (Opcode < ISD::BUILTIN_OP_END) + return PseudoInst; + Opcode -= ISD::BUILTIN_OP_END; + + switch (Opcode) { + case PPC::FMRSD: return PseudoInst; // Usually coallesced away. + case PPC::BCTRL: + case PPC::BL: + case PPC::BLA: + return BR; + case PPC::LFS: + case PPC::LWZ: + return LSU_LD; + case PPC::STFD: + return LSU_ST; + case PPC::FADDS: + case PPC::FCTIWZ: + return FPU; + } + + return FXU; +} + + +/// StartBasicBlock - Initiate a new dispatch group. +void PPCHazardRecognizer970::StartBasicBlock() { + EndDispatchGroup(); +} + +/// 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(StorePtr1)) + if (ConstantSDNode *LoadOffset = dyn_cast(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; +} + +/// getHazardType - We return hazard for any non-branch instruction that would +/// terminate terminate the dispatch group. We turn NoopHazard for any +/// instructions that wouldn't terminate the dispatch group that would cause a +/// pipeline flush. +HazardRecognizer::HazardType PPCHazardRecognizer970:: +getHazardType(SDNode *Node) { + PPC970InstrType InstrType = GetInstrType(Node->getOpcode()); + if (InstrType == PseudoInst) return NoHazard; + unsigned Opcode = Node->getOpcode()-ISD::BUILTIN_OP_END; + + switch (InstrType) { + default: assert(0 && "Unknown instruction type!"); + case FXU: 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 VALU: if (HasVALU) return Hazard; + case VPERM: if (HasVPERM) return Hazard; + case BR: break; + } + + // 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) { + unsigned LoadSize; + switch (Opcode) { + default: assert(0 && "Unknown load!"); + case PPC::LFS: + case PPC::LWZ: LoadSize = 4; break; + } + + if (isLoadOfStoredAddress(LoadSize, + Node->getOperand(0), Node->getOperand(1))) + return NoopHazard; + } + + return NoHazard; +} + +void PPCHazardRecognizer970::EmitInstruction(SDNode *Node) { + PPC970InstrType InstrType = GetInstrType(Node->getOpcode()); + if (InstrType == PseudoInst) 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); + switch (Opcode) { + default: assert(0 && "Unknown store instruction!"); + case PPC::STFD: StoreSize = 8; break; + } + } + + switch (InstrType) { + default: assert(0 && "Unknown instruction type!"); + case FXU: ++NumFXU; break; + case LSU_LD: + case LSU_ST: ++NumLSU; break; + case FPU: ++NumFPU; break; + case CR: HasCR = true; break; + case VALU: HasVALU = true; break; + case VPERM: HasVPERM = true; break; + case BR: NumIssued = 4; return; // ends a d-group. + } + ++NumIssued; + + if (NumIssued == 5) + EndDispatchGroup(); +} + +void PPCHazardRecognizer970::AdvanceCycle() { + assert(NumIssued < 5 && "Illegal dispatch group!"); + ++NumIssued; + if (NumIssued == 5) + EndDispatchGroup(); +} + +void PPCHazardRecognizer970::EmitNoop() { + AdvanceCycle(); +} diff --git a/lib/Target/PowerPC/PPCHazardRecognizers.h b/lib/Target/PowerPC/PPCHazardRecognizers.h new file mode 100644 index 00000000000..f11d3e68292 --- /dev/null +++ b/lib/Target/PowerPC/PPCHazardRecognizers.h @@ -0,0 +1,79 @@ +//===-- PPCHazardRecognizers.h - PowerPC Hazard Recognizers -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines hazard recognizers for scheduling on PowerPC processors. +// +//===----------------------------------------------------------------------===// + +#ifndef PPCHAZRECS_H +#define PPCHAZRECS_H + +#include "llvm/CodeGen/ScheduleDAG.h" + +namespace llvm { + +/// PPCHazardRecognizer970 - This class defines a finite state automata that +/// models the dispatch logic on the PowerPC 970 (aka G5) processor. This +/// promotes good dispatch group formation and implements noop insertion to +/// avoid structural hazards that cause significant performance penalties (e.g. +/// setting the CTR register then branching through it within a dispatch group), +/// or storing then loading from the same address within a dispatch group. +class PPCHazardRecognizer970 : public HazardRecognizer { + unsigned NumIssued; // Number of insts issued, including advanced cycles. + + // Number of various types of instructions in the current dispatch group. + unsigned NumFXU; // Number of Fixed Point (integer) instructions + unsigned NumLSU; // Number of Load/Store instructions + unsigned NumFPU; // Number of Floating Point instructions + bool HasCR; // True if Condition Register instruction issued + bool HasVALU; // True if Vector Arithmetic instruction issued + bool HasVPERM; // True if Vector Permute instruction issued + + // Various things that can cause a structural hazard. + + // HasCTRSet - If the CTR register is set in this group, disallow BCTRL. + bool HasCTRSet; + + // StoredPtr - Keep track of the address of any store. If we see a load from + // the same address (or one that aliases it), disallow the store. We only + // need one pointer here, because there can only be two LSU operations and we + // only get an LSU reject if the first is a store and the second is a load. + // + // This is null if we haven't seen a store yet. We keep track of both + // operands of the store here, since we support [r+r] and [r+i] addressing. + SDOperand StorePtr1, StorePtr2; + unsigned StoreSize; + +public: + virtual void StartBasicBlock(); + virtual HazardType getHazardType(SDNode *Node); + virtual void EmitInstruction(SDNode *Node); + virtual void AdvanceCycle(); + virtual void EmitNoop(); + +private: + /// EndDispatchGroup - Called when we are finishing a new dispatch group. + /// + void EndDispatchGroup(); + + enum PPC970InstrType { + FXU, LSU_LD, LSU_ST, FPU, CR, VALU, VPERM, BR, PseudoInst + }; + + /// GetInstrType - Classify the specified powerpc opcode according to its + /// pipeline. + PPC970InstrType GetInstrType(unsigned Opcode); + + bool isLoadOfStoredAddress(unsigned LoadSize, + SDOperand Ptr1, SDOperand Ptr2) const; +}; + +} // end namespace llvm + +#endif \ No newline at end of file diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 185afd1a6d7..5c74a7ba6cd 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -15,6 +15,7 @@ #include "PPC.h" #include "PPCTargetMachine.h" #include "PPCISelLowering.h" +#include "PPCHazardRecognizers.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SSARegMap.h" @@ -40,6 +41,7 @@ namespace { class PPCDAGToDAGISel : public SelectionDAGISel { PPCTargetLowering PPCLowering; unsigned GlobalBaseReg; + PPCHazardRecognizer970 PPC970HR; public: PPCDAGToDAGISel(TargetMachine &TM) : SelectionDAGISel(PPCLowering), PPCLowering(TM) {} @@ -122,13 +124,19 @@ namespace { virtual const char *getPassName() const { return "PowerPC DAG->DAG Pattern Instruction Selection"; } + + /// GetTargetHazardRecognizer - Return the hazard recognizer to use for this + /// target when scheduling the DAG. + virtual HazardRecognizer &GetTargetHazardRecognizer() { + // Should use subtarget info to pick the right hazard recognizer. For + // now, always return a PPC970 recognizer. + return PPC970HR; + } // Include the pieces autogenerated from the target description. #include "PPCGenDAGISel.inc" private: - SDOperand SelectADD_PARTS(SDOperand Op); - SDOperand SelectSUB_PARTS(SDOperand Op); SDOperand SelectSETCC(SDOperand Op); SDOperand SelectCALL(SDOperand Op); };