Changes in directory llvm/lib/Target/PowerPC:
PPCHazardRecognizers.cpp added (r1.1) PPCHazardRecognizers.h added (r1.1) PPCISelDAGToDAG.cpp updated: 1.161 -> 1.162 --- Log message: Implement a very very simple hazard recognizer for LSU rejects and ctr set/read flushes --- Diffs of the changes: (+292 -2) PPCHazardRecognizers.cpp | 203 +++++++++++++++++++++++++++++++++++++++++++++++ PPCHazardRecognizers.h | 79 ++++++++++++++++++ PPCISelDAGToDAG.cpp | 12 ++ 3 files changed, 292 insertions(+), 2 deletions(-) Index: llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp diff -c /dev/null llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp:1.1 *** /dev/null Tue Mar 7 00:32:58 2006 --- llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp Tue Mar 7 00:32:48 2006 *************** *** 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 <iostream> + 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<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; + } + } + } + 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(); + } Index: llvm/lib/Target/PowerPC/PPCHazardRecognizers.h diff -c /dev/null llvm/lib/Target/PowerPC/PPCHazardRecognizers.h:1.1 *** /dev/null Tue Mar 7 00:33:01 2006 --- llvm/lib/Target/PowerPC/PPCHazardRecognizers.h Tue Mar 7 00:32:48 2006 *************** *** 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 Index: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp diff -u llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.161 llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.162 --- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp:1.161 Wed Mar 1 01:14:48 2006 +++ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp Tue Mar 7 00:32:48 2006 @@ -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 @@ class PPCDAGToDAGISel : public SelectionDAGISel { PPCTargetLowering PPCLowering; unsigned GlobalBaseReg; + PPCHazardRecognizer970 PPC970HR; public: PPCDAGToDAGISel(TargetMachine &TM) : SelectionDAGISel(PPCLowering), PPCLowering(TM) {} @@ -122,13 +124,19 @@ 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); }; _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits