--- /dev/null
+//===-- 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();
+}
--- /dev/null
+//===-- 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
#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"
class PPCDAGToDAGISel : public SelectionDAGISel {
PPCTargetLowering PPCLowering;
unsigned GlobalBaseReg;
+ PPCHazardRecognizer970 PPC970HR;
public:
PPCDAGToDAGISel(TargetMachine &TM)
: SelectionDAGISel(PPCLowering), PPCLowering(TM) {}
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);
};