From: Chris Lattner Date: Fri, 14 Sep 2001 05:34:53 +0000 (+0000) Subject: Make a new llvm/Target #include directory. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b26bcc5087029ffe8037ed9036ff74430c6054cf;p=oota-llvm.git Make a new llvm/Target #include directory. Move files from lib/CodeGen/TargetMachine to lib/Target Move TargetData.h and TargetMachine.h to Target/{Data.h|Machine.h} Prepare to split TargetMachine.h into several smaller files git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@566 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 43dc78dfc55..9903f09c01d 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -19,7 +19,7 @@ #include "llvm/CodeGen/InstrForest.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/NonCopyable.h" -#include "llvm/CodeGen/TargetMachine.h" +#include "llvm/Target/Machine.h" template class ValOpIterator; diff --git a/include/llvm/CodeGen/RegClass.h b/include/llvm/CodeGen/RegClass.h index 1d08502445d..efe174617ce 100644 --- a/include/llvm/CodeGen/RegClass.h +++ b/include/llvm/CodeGen/RegClass.h @@ -16,19 +16,14 @@ */ - - #ifndef REG_CLASS_H #define REG_CLASS_H #include "llvm/CodeGen/IGNode.h" #include "llvm/CodeGen/InterferenceGraph.h" -#include "llvm/CodeGen/TargetMachine.h" - - +#include "llvm/Target/Machine.h" #include - typedef vector ReservedColorListType; diff --git a/include/llvm/CodeGen/Sparc.h b/include/llvm/CodeGen/Sparc.h deleted file mode 100644 index 83bebbddaf3..00000000000 --- a/include/llvm/CodeGen/Sparc.h +++ /dev/null @@ -1,17 +0,0 @@ -//===-- llvm/CodeGen/Sparc.h - Sparc Target Description ----------*- C++ -*--=// -// -// This file defines the Sparc processor targets -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_SPARC_H -#define LLVM_CODEGEN_SPARC_H - -class TargetMachine; - -// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine -// that implements the Sparc backend. -// -TargetMachine *allocateSparcTargetMachine(); - -#endif diff --git a/include/llvm/CodeGen/TargetData.h b/include/llvm/CodeGen/TargetData.h deleted file mode 100644 index cf449702b7b..00000000000 --- a/include/llvm/CodeGen/TargetData.h +++ /dev/null @@ -1,85 +0,0 @@ -//===-- llvm/TargetData.h - Data size & alignment routines -------*- C++ -*-==// -// -// This file defines target properties related to datatype size/offset/alignment -// information. It uses lazy annotations to cache information about how -// structure types are laid out and used. -// -// This structure should be created once, filled in if the defaults are not -// correct and then passed around by const&. None of the members functions -// require modification to the object. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_TARGETDATA_H -#define LLVM_CODEGEN_TARGETDATA_H - -#include "llvm/Type.h" -#include - -class StructType; -class StructLayout; - -class TargetData { - unsigned char ByteAlignment; // Defaults to 1 bytes - unsigned char ShortAlignment; // Defaults to 2 bytes - unsigned char IntAlignment; // Defaults to 4 bytes - unsigned char LongAlignment; // Defaults to 8 bytes - unsigned char FloatAlignment; // Defaults to 4 bytes - unsigned char DoubleAlignment; // Defaults to 8 bytes - unsigned char PointerSize; // Defaults to 8 bytes - unsigned char PointerAlignment; // Defaults to 8 bytes - AnnotationID AID; // AID for structure layout annotation - - static Annotation *TypeAnFactory(AnnotationID, const Annotable *, void *); -public: - TargetData(const string &TargetName, unsigned char PtrSize = 8, - unsigned char PtrAl = 8, unsigned char DoubleAl = 8, - unsigned char FloatAl = 4, unsigned char LongAl = 8, - unsigned char IntAl = 4, unsigned char ShortAl = 2, - unsigned char ByteAl = 1); - ~TargetData(); // Not virtual, do not subclass this class - - unsigned char getByteAlignment() const { return ByteAlignment; } - unsigned char getShortAlignment() const { return ShortAlignment; } - unsigned char getIntAlignment() const { return IntAlignment; } - unsigned char getLongAlignment() const { return LongAlignment; } - unsigned char getFloatAlignment() const { return FloatAlignment; } - unsigned char getDoubleAlignment() const { return DoubleAlignment; } - unsigned char getPointerAlignment() const { return PointerAlignment; } - unsigned char getPointerSize() const { return PointerSize; } - AnnotationID getStructLayoutAID() const { return AID; } - - // getTypeSize - Return the number of bytes neccesary to hold the specified - // type - unsigned getTypeSize (const Type *Ty) const; - - // getTypeAlignment - Return the minimum required alignment for the specified - // type - unsigned char getTypeAlignment(const Type *Ty) const; - - // getIndexOffset - return the offset from the beginning of the type for the - // specified indices. This is used to implement getElementPtr and load and - // stores that include the implicit form of getelementptr. - // - unsigned getIndexedOffset(const Type *Ty, - const vector &Indices) const; - - inline const StructLayout *getStructLayout(const StructType *Ty) const { - return (const StructLayout*)((const Type*)Ty)->getOrCreateAnnotation(AID); - } -}; - -// This annotation (attached ONLY to StructType classes) is used to lazily -// calculate structure layout information for a target machine, based on the -// TargetData structure. -// -struct StructLayout : public Annotation { - vector MemberOffsets; - unsigned StructSize; - unsigned StructAlignment; -private: - friend class TargetData; // Only TargetData can create this class - inline StructLayout(const StructType *ST, const TargetData &TD); -}; - -#endif diff --git a/include/llvm/CodeGen/TargetMachine.h b/include/llvm/CodeGen/TargetMachine.h deleted file mode 100644 index 9a72ff974b9..00000000000 --- a/include/llvm/CodeGen/TargetMachine.h +++ /dev/null @@ -1,787 +0,0 @@ -// $Id$ -*-c++-*- -//*************************************************************************** -// File: -// TargetMachine.h -// -// Purpose: -// -// History: -// 7/12/01 - Vikram Adve - Created -//**************************************************************************/ - -#ifndef LLVM_CODEGEN_TARGETMACHINE_H -#define LLVM_CODEGEN_TARGETMACHINE_H - -#include "llvm/CodeGen/TargetData.h" -#include "llvm/Support/NonCopyable.h" -#include "llvm/Support/DataTypes.h" -#include -#include -#include -#include - -class StructType; -struct MachineInstrDescriptor; -class TargetMachine; - -//************************ Exported Data Types *****************************/ - -//--------------------------------------------------------------------------- -// Data types used to define information about a single machine instruction -//--------------------------------------------------------------------------- - -typedef int MachineOpCode; -typedef int OpCodeMask; -typedef int InstrSchedClass; - -static const unsigned MAX_OPCODE_SIZE = 16; - -typedef long long cycles_t; -const cycles_t HUGE_LATENCY = ~((unsigned long long) 1 << sizeof(cycles_t)-1); -const cycles_t INVALID_LATENCY = -HUGE_LATENCY; - - -class OpCodePair { -public: - long val; // make long by concatenating two opcodes - OpCodePair(MachineOpCode op1, MachineOpCode op2) - : val((op1 < 0 || op2 < 0)? - -1 : (long)((((unsigned) op1) << MAX_OPCODE_SIZE) | (unsigned) op2)) {} - bool operator==(const OpCodePair& op) const { - return val == op.val; - } -private: - OpCodePair(); // disable for now -}; - - -template <> struct hash { - size_t operator()(const OpCodePair& pair) const { - return hash()(pair.val); - } -}; - - -// Global variable holding an array of descriptors for machine instructions. -// The actual object needs to be created separately for each target machine. -// This variable is initialized and reset by class MachineInstrInfo. -// -extern const MachineInstrDescriptor* TargetInstrDescriptors; - - -//--------------------------------------------------------------------------- -// struct MachineInstrDescriptor: -// Predefined information about each machine instruction. -// Designed to initialized statically. -// -// class MachineInstructionInfo -// Interface to description of machine instructions -// -//--------------------------------------------------------------------------- - - -const unsigned int M_NOP_FLAG = 1; -const unsigned int M_BRANCH_FLAG = 1 << 1; -const unsigned int M_CALL_FLAG = 1 << 2; -const unsigned int M_RET_FLAG = 1 << 3; -const unsigned int M_ARITH_FLAG = 1 << 4; -const unsigned int M_CC_FLAG = 1 << 6; -const unsigned int M_LOGICAL_FLAG = 1 << 6; -const unsigned int M_INT_FLAG = 1 << 7; -const unsigned int M_FLOAT_FLAG = 1 << 8; -const unsigned int M_CONDL_FLAG = 1 << 9; -const unsigned int M_LOAD_FLAG = 1 << 10; -const unsigned int M_PREFETCH_FLAG = 1 << 11; -const unsigned int M_STORE_FLAG = 1 << 12; -const unsigned int M_DUMMY_PHI_FLAG = 1 << 13; - - -struct MachineInstrDescriptor { - string opCodeString; // Assembly language mnemonic for the opcode. - int numOperands; // Number of args; -1 if variable #args - int resultPos; // Position of the result; -1 if no result - unsigned int maxImmedConst; // Largest +ve constant in IMMMED field or 0. - bool immedIsSignExtended; // Is IMMED field sign-extended? If so, - // smallest -ve value is -(maxImmedConst+1). - unsigned int numDelaySlots; // Number of delay slots after instruction - unsigned int latency; // Latency in machine cycles - InstrSchedClass schedClass; // enum identifying instr sched class - unsigned int iclass; // flags identifying machine instr class -}; - - -class MachineInstrInfo : public NonCopyableV { -protected: - const MachineInstrDescriptor* desc; // raw array to allow static init'n - unsigned int descSize; // number of entries in the desc array - unsigned int numRealOpCodes; // number of non-dummy op codes - -public: - /*ctor*/ MachineInstrInfo(const MachineInstrDescriptor* _desc, - unsigned int _descSize, - unsigned int _numRealOpCodes); - /*dtor*/ virtual ~MachineInstrInfo(); - - unsigned int getNumRealOpCodes() const { - return numRealOpCodes; - } - - unsigned int getNumTotalOpCodes() const { - return descSize; - } - - const MachineInstrDescriptor& getDescriptor(MachineOpCode opCode) const { - assert(opCode >= 0 && opCode < (int) descSize); - return desc[opCode]; - } - - int getNumOperands (MachineOpCode opCode) const { - return getDescriptor(opCode).numOperands; - } - - int getResultPos (MachineOpCode opCode) const { - return getDescriptor(opCode).resultPos; - } - - unsigned int getNumDelaySlots(MachineOpCode opCode) const { - return getDescriptor(opCode).numDelaySlots; - } - - InstrSchedClass getSchedClass (MachineOpCode opCode) const { - return getDescriptor(opCode).schedClass; - } - - // - // Query instruction class flags according to the machine-independent - // flags listed above. - // - unsigned int getIClass (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass; - } - bool isNop (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_NOP_FLAG; - } - bool isBranch (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_BRANCH_FLAG; - } - bool isCall (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_CALL_FLAG; - } - bool isReturn (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_RET_FLAG; - } - bool isControlFlow (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_BRANCH_FLAG - || getDescriptor(opCode).iclass & M_CALL_FLAG - || getDescriptor(opCode).iclass & M_RET_FLAG; - } - bool isArith (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_RET_FLAG; - } - bool isCCInstr (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_CC_FLAG; - } - bool isLogical (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_LOGICAL_FLAG; - } - bool isIntInstr (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_INT_FLAG; - } - bool isFloatInstr (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_FLOAT_FLAG; - } - bool isConditional (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_CONDL_FLAG; - } - bool isLoad (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_LOAD_FLAG; - } - bool isPrefetch (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_PREFETCH_FLAG; - } - bool isLoadOrPrefetch (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_LOAD_FLAG - || getDescriptor(opCode).iclass & M_PREFETCH_FLAG; - } - bool isStore (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_STORE_FLAG; - } - bool isMemoryAccess (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_LOAD_FLAG - || getDescriptor(opCode).iclass & M_PREFETCH_FLAG - || getDescriptor(opCode).iclass & M_STORE_FLAG; - } - bool isDummyPhiInstr (MachineOpCode opCode) const { - return getDescriptor(opCode).iclass & M_DUMMY_PHI_FLAG; - } - - - // delete this later ******* - bool isPhi(MachineOpCode opCode) { return isDummyPhiInstr(opCode); } - - - - // Check if an instruction can be issued before its operands are ready, - // or if a subsequent instruction that uses its result can be issued - // before the results are ready. - // Default to true since most instructions on many architectures allow this. - // - virtual bool hasOperandInterlock(MachineOpCode opCode) const { - return true; - } - - virtual bool hasResultInterlock(MachineOpCode opCode) const { - return true; - } - - // - // Latencies for individual instructions and instruction pairs - // - virtual int minLatency (MachineOpCode opCode) const { - return getDescriptor(opCode).latency; - } - - virtual int maxLatency (MachineOpCode opCode) const { - return getDescriptor(opCode).latency; - } - - // Check if the specified constant fits in the immediate field - // of this machine instruction - // - virtual bool constantFitsInImmedField(MachineOpCode opCode, - int64_t intValue) const; - - // Return the largest +ve constant that can be held in the IMMMED field - // of this machine instruction. - // isSignExtended is set to true if the value is sign-extended before use - // (this is true for all immediate fields in SPARC instructions). - // Return 0 if the instruction has no IMMED field. - // - virtual uint64_t maxImmedConstant(MachineOpCode opCode, - bool& isSignExtended) const { - isSignExtended = getDescriptor(opCode).immedIsSignExtended; - return getDescriptor(opCode).maxImmedConst; - } -}; - - -//--------------------------------------------------------------------------- -// class MachineResource -// class CPUResource -// -// Purpose: -// Representation of a single machine resource used in specifying -// resource usages of machine instructions for scheduling. -//--------------------------------------------------------------------------- - - -typedef unsigned int resourceId_t; - -class MachineResource { -public: - const string rname; - resourceId_t rid; - - /*ctor*/ MachineResource(const string& resourceName) - : rname(resourceName), rid(nextId++) {} - -private: - static resourceId_t nextId; - MachineResource(); // disable -}; - - -class CPUResource : public MachineResource { -public: - int maxNumUsers; // MAXINT if no restriction - - /*ctor*/ CPUResource(const string& rname, int maxUsers) - : MachineResource(rname), maxNumUsers(maxUsers) {} -}; - - -//--------------------------------------------------------------------------- -// struct InstrClassRUsage -// struct InstrRUsageDelta -// struct InstrIssueDelta -// struct InstrRUsage -// -// Purpose: -// The first three are structures used to specify machine resource -// usages for each instruction in a machine description file: -// InstrClassRUsage : resource usages common to all instrs. in a class -// InstrRUsageDelta : add/delete resource usage for individual instrs. -// InstrIssueDelta : add/delete instr. issue info for individual instrs -// -// The last one (InstrRUsage) is the internal representation of -// instruction resource usage constructed from the above three. -//--------------------------------------------------------------------------- - -const int MAX_NUM_SLOTS = 32; -const int MAX_NUM_CYCLES = 32; - -struct InstrClassRUsage { - InstrSchedClass schedClass; - int totCycles; - - // Issue restrictions common to instructions in this class - unsigned int maxNumIssue; - bool isSingleIssue; - bool breaksGroup; - cycles_t numBubbles; - - // Feasible slots to use for instructions in this class. - // The size of vector S[] is `numSlots'. - unsigned int numSlots; - unsigned int feasibleSlots[MAX_NUM_SLOTS]; - - // Resource usages common to instructions in this class. - // The size of vector V[] is `numRUEntries'. - unsigned int numRUEntries; - struct { - resourceId_t resourceId; - unsigned int startCycle; - int numCycles; - } V[MAX_NUM_CYCLES]; -}; - -struct InstrRUsageDelta { - MachineOpCode opCode; - resourceId_t resourceId; - unsigned int startCycle; - int numCycles; -}; - -// Specify instruction issue restrictions for individual instructions -// that differ from the common rules for the class. -// -struct InstrIssueDelta { - MachineOpCode opCode; - bool isSingleIssue; - bool breaksGroup; - cycles_t numBubbles; -}; - - -struct InstrRUsage { - /*ctor*/ InstrRUsage () {} - /*ctor*/ InstrRUsage (const InstrRUsage& instrRU); - InstrRUsage& operator= (const InstrRUsage& instrRU); - - bool sameAsClass; - - // Issue restrictions for this instruction - bool isSingleIssue; - bool breaksGroup; - cycles_t numBubbles; - - // Feasible slots to use for this instruction. - vector feasibleSlots; - - // Resource usages for this instruction, with one resource vector per cycle. - cycles_t numCycles; - vector > resourcesByCycle; - -private: - // Conveniences for initializing this structure - InstrRUsage& operator= (const InstrClassRUsage& classRU); - void addIssueDelta (const InstrIssueDelta& delta); - void addUsageDelta (const InstrRUsageDelta& delta); - void setMaxSlots (int maxNumSlots); - - friend class MachineSchedInfo; // give access to these functions -}; - - -inline void -InstrRUsage::setMaxSlots(int maxNumSlots) -{ - feasibleSlots.resize(maxNumSlots); -} - -inline InstrRUsage& -InstrRUsage::operator=(const InstrRUsage& instrRU) -{ - sameAsClass = instrRU.sameAsClass; - isSingleIssue = instrRU.isSingleIssue; - breaksGroup = instrRU.breaksGroup; - numBubbles = instrRU.numBubbles; - feasibleSlots = instrRU.feasibleSlots; - numCycles = instrRU.numCycles; - resourcesByCycle = instrRU.resourcesByCycle; - return *this; -} - -inline /*ctor*/ -InstrRUsage::InstrRUsage(const InstrRUsage& instrRU) -{ - *this = instrRU; -} - -inline InstrRUsage& -InstrRUsage::operator=(const InstrClassRUsage& classRU) -{ - sameAsClass = true; - isSingleIssue = classRU.isSingleIssue; - breaksGroup = classRU.breaksGroup; - numBubbles = classRU.numBubbles; - - for (unsigned i=0; i < classRU.numSlots; i++) - { - unsigned slot = classRU.feasibleSlots[i]; - assert(slot < feasibleSlots.size() && "Invalid slot specified!"); - this->feasibleSlots[slot] = true; - } - - this->numCycles = classRU.totCycles; - this->resourcesByCycle.resize(this->numCycles); - - for (unsigned i=0; i < classRU.numRUEntries; i++) - for (unsigned c=classRU.V[i].startCycle, NC = c + classRU.V[i].numCycles; - c < NC; c++) - this->resourcesByCycle[c].push_back(classRU.V[i].resourceId); - - // Sort each resource usage vector by resourceId_t to speed up conflict checking - for (unsigned i=0; i < this->resourcesByCycle.size(); i++) - sort(resourcesByCycle[i].begin(), resourcesByCycle[i].end()); - - return *this; -} - - -inline void -InstrRUsage::addIssueDelta(const InstrIssueDelta& delta) -{ - sameAsClass = false; - isSingleIssue = delta.isSingleIssue; - breaksGroup = delta.breaksGroup; - numBubbles = delta.numBubbles; -} - - -// Add the extra resource usage requirements specified in the delta. -// Note that a negative value of `numCycles' means one entry for that -// resource should be deleted for each cycle. -// -inline void -InstrRUsage::addUsageDelta(const InstrRUsageDelta& delta) -{ - int NC = delta.numCycles; - - this->sameAsClass = false; - - // resize the resources vector if more cycles are specified - unsigned maxCycles = this->numCycles; - maxCycles = max(maxCycles, delta.startCycle + abs(NC) - 1); - if (maxCycles > this->numCycles) - { - this->resourcesByCycle.resize(maxCycles); - this->numCycles = maxCycles; - } - - if (NC >= 0) - for (unsigned c=delta.startCycle, last=c+NC-1; c <= last; c++) - this->resourcesByCycle[c].push_back(delta.resourceId); - else - // Remove the resource from all NC cycles. - for (unsigned c=delta.startCycle, last=(c-NC)-1; c <= last; c++) - { - // Look for the resource backwards so we remove the last entry - // for that resource in each cycle. - vector& rvec = this->resourcesByCycle[c]; - int r; - for (r = (int) rvec.size(); r >= 0; r--) - if (rvec[r] == delta.resourceId) - {// found last entry for the resource - rvec.erase(rvec.begin() + r); - break; - } - assert(r >= 0 && "Resource to remove was unused in cycle c!"); - } -} - - -//--------------------------------------------------------------------------- -// class MachineSchedInfo -// -// Purpose: -// Common interface to machine information for instruction scheduling -//--------------------------------------------------------------------------- - -class MachineSchedInfo : public NonCopyableV { -public: - unsigned int maxNumIssueTotal; - int longestIssueConflict; - - int branchMispredictPenalty; // 4 for SPARC IIi - int branchTargetUnknownPenalty; // 2 for SPARC IIi - int l1DCacheMissPenalty; // 7 or 9 for SPARC IIi - int l1ICacheMissPenalty; // ? for SPARC IIi - - bool inOrderLoads ; // true for SPARC IIi - bool inOrderIssue; // true for SPARC IIi - bool inOrderExec; // false for most architectures - bool inOrderRetire; // true for most architectures - -protected: - inline const InstrRUsage& getInstrRUsage(MachineOpCode opCode) const { - assert(opCode >= 0 && opCode < (int) instrRUsages.size()); - return instrRUsages[opCode]; - } - inline const InstrClassRUsage& - getClassRUsage(const InstrSchedClass& sc) const { - assert(sc >= 0 && sc < numSchedClasses); - return classRUsages[sc]; - } - -public: - /*ctor*/ MachineSchedInfo (int _numSchedClasses, - const MachineInstrInfo* _mii, - const InstrClassRUsage* _classRUsages, - const InstrRUsageDelta* _usageDeltas, - const InstrIssueDelta* _issueDeltas, - unsigned int _numUsageDeltas, - unsigned int _numIssueDeltas); - /*dtor*/ virtual ~MachineSchedInfo () {} - - inline const MachineInstrInfo& getInstrInfo() const { - return *mii; - } - - inline int getNumSchedClasses() const { - return numSchedClasses; - } - - inline unsigned int getMaxNumIssueTotal() const { - return maxNumIssueTotal; - } - - inline unsigned int getMaxIssueForClass(const InstrSchedClass& sc) const { - assert(sc >= 0 && sc < numSchedClasses); - return classRUsages[sc].maxNumIssue; - } - - inline InstrSchedClass getSchedClass (MachineOpCode opCode) const { - return getInstrInfo().getSchedClass(opCode); - } - - inline bool instrCanUseSlot (MachineOpCode opCode, - unsigned s) const { - assert(s < getInstrRUsage(opCode).feasibleSlots.size() && "Invalid slot!"); - return getInstrRUsage(opCode).feasibleSlots[s]; - } - - inline int getLongestIssueConflict () const { - return longestIssueConflict; - } - - inline int getMinIssueGap (MachineOpCode fromOp, - MachineOpCode toOp) const { - hash_map::const_iterator - I = issueGaps.find(OpCodePair(fromOp, toOp)); - return (I == issueGaps.end())? 0 : (*I).second; - } - - inline const vector* - getConflictList(MachineOpCode opCode) const { - hash_map >::const_iterator - I = conflictLists.find(opCode); - return (I == conflictLists.end())? NULL : & (*I).second; - } - - inline bool isSingleIssue (MachineOpCode opCode) const { - return getInstrRUsage(opCode).isSingleIssue; - } - - inline bool breaksIssueGroup (MachineOpCode opCode) const { - return getInstrRUsage(opCode).breaksGroup; - } - - inline unsigned int numBubblesAfter (MachineOpCode opCode) const { - return getInstrRUsage(opCode).numBubbles; - } - -protected: - virtual void initializeResources (); - -private: - void computeInstrResources(const vector& instrRUForClasses); - void computeIssueGaps(const vector& instrRUForClasses); - -protected: - int numSchedClasses; - const MachineInstrInfo* mii; - const InstrClassRUsage* classRUsages; // raw array by sclass - const InstrRUsageDelta* usageDeltas; // raw array [1:numUsageDeltas] - const InstrIssueDelta* issueDeltas; // raw array [1:numIssueDeltas] - unsigned int numUsageDeltas; - unsigned int numIssueDeltas; - - vector instrRUsages; // indexed by opcode - hash_map issueGaps; // indexed by opcode pair - hash_map > - conflictLists; // indexed by opcode -}; - - - -//----------------------------------------------------------------------------- -// class MachineRegClassInfo -// -// Purpose: -// Interface to description of machine register class (e.g., int reg class -// float reg class etc) -// -//-------------------------------------------------------------------------- - -class IGNode; - - -class MachineRegClassInfo { - -protected: - - const unsigned RegClassID; // integer ID of a reg class - const unsigned NumOfAvailRegs; // # of avail for coloring -without SP etc. - const unsigned NumOfAllRegs; // # of all registers -including SP,g0 etc. - -public: - - inline unsigned getRegClassID() const { return RegClassID; } - inline unsigned getNumOfAvailRegs() const { return NumOfAvailRegs; } - inline unsigned getNumOfAllRegs() const { return NumOfAllRegs; } - - - - // This method should find a color which is not used by neighbors - // (i.e., a false position in IsColorUsedArr) and - virtual void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const = 0; - - - MachineRegClassInfo(const unsigned ID, const unsigned NVR, - const unsigned NAR): RegClassID(ID), NumOfAvailRegs(NVR), - NumOfAllRegs(NAR) - { } // empty constructor - -}; - - - - -//--------------------------------------------------------------------------- -// class MachineRegInfo -// -// Purpose: -// Interface to register info of target machine -// -//-------------------------------------------------------------------------- - -class LiveRangeInfo; -class Method; -class Instruction; -class LiveRange; -class AddedInstrns; -class MachineInstr; -typedef hash_map AddedInstrMapType; - -// A vector of all machine register classes -typedef vector MachineRegClassArrayType; - - -class MachineRegInfo : public NonCopyableV { - -protected: - - MachineRegClassArrayType MachineRegClassArr; - - -public: - - - inline unsigned int getNumOfRegClasses() const { - return MachineRegClassArr.size(); - } - - const MachineRegClassInfo *const getMachineRegClass(unsigned i) const { - return MachineRegClassArr[i]; - } - - - virtual unsigned getRegClassIDOfValue (const Value *const Val) const = 0; - - virtual void colorArgs(const Method *const Meth, - LiveRangeInfo & LRI) const = 0; - - virtual void colorCallArgs(vector & CallInstrList, - LiveRangeInfo& LRI, - AddedInstrMapType& AddedInstrMap ) const = 0 ; - - virtual int getUnifiedRegNum(int RegClassID, int reg) const = 0; - - virtual const string getUnifiedRegName(int reg) const = 0; - - //virtual void printReg(const LiveRange *const LR) const =0; - - MachineRegInfo() { } - -}; - - - - - -//--------------------------------------------------------------------------- -// class TargetMachine -// -// Purpose: -// Primary interface to machine description for the target machine. -// -//--------------------------------------------------------------------------- - -class TargetMachine : public NonCopyableV { -public: - const string TargetName; - const TargetData DataLayout; // Calculates type size & alignment - int optSizeForSubWordData; - int minMemOpWordSize; - int maxAtomicMemOpWordSize; - - // Register information. This needs to be reorganized into a single class. - int zeroRegNum; // register that gives 0 if any (-1 if none) - -public: - TargetMachine(const string &targetname, - unsigned char PtrSize = 8, unsigned char PtrAl = 8, - unsigned char DoubleAl = 8, unsigned char FloatAl = 4, - unsigned char LongAl = 8, unsigned char IntAl = 4, - unsigned char ShortAl = 2, unsigned char ByteAl = 1) - : TargetName(targetname), DataLayout(targetname, PtrSize, PtrAl, - DoubleAl, FloatAl, LongAl, IntAl, - ShortAl, ByteAl) { } - virtual ~TargetMachine() {} - - virtual const MachineInstrInfo& getInstrInfo() const = 0; - - virtual unsigned int findOptimalStorageSize (const Type* ty) const; - - // This really should be in the register info class - virtual bool regsMayBeAliased (unsigned int regNum1, - unsigned int regNum2) const { - return (regNum1 == regNum2); - } - - // compileMethod - This does everything neccesary to compile a method into the - // built in representation. This allows the target to have complete control - // over how it does compilation. This does not emit assembly or output - // machine code however, this is done later. - // - virtual bool compileMethod(Method *M) = 0; - - // emitAssembly - Output assembly language code (a .s file) for the specified - // method. The specified method must have been compiled before this may be - // used. - // - virtual void emitAssembly(Method *M, ostream &OutStr) { /* todo */ } -}; - -#endif diff --git a/include/llvm/Target/Data.h b/include/llvm/Target/Data.h new file mode 100644 index 00000000000..55739503e72 --- /dev/null +++ b/include/llvm/Target/Data.h @@ -0,0 +1,85 @@ +//===-- llvm/Target/Data.h - Data size & alignment routines ------*- C++ -*-==// +// +// This file defines target properties related to datatype size/offset/alignment +// information. It uses lazy annotations to cache information about how +// structure types are laid out and used. +// +// This structure should be created once, filled in if the defaults are not +// correct and then passed around by const&. None of the members functions +// require modification to the object. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_DATA_H +#define LLVM_TARGET_DATA_H + +#include "llvm/Type.h" +#include + +class StructType; +class StructLayout; + +class TargetData { + unsigned char ByteAlignment; // Defaults to 1 bytes + unsigned char ShortAlignment; // Defaults to 2 bytes + unsigned char IntAlignment; // Defaults to 4 bytes + unsigned char LongAlignment; // Defaults to 8 bytes + unsigned char FloatAlignment; // Defaults to 4 bytes + unsigned char DoubleAlignment; // Defaults to 8 bytes + unsigned char PointerSize; // Defaults to 8 bytes + unsigned char PointerAlignment; // Defaults to 8 bytes + AnnotationID AID; // AID for structure layout annotation + + static Annotation *TypeAnFactory(AnnotationID, const Annotable *, void *); +public: + TargetData(const string &TargetName, unsigned char PtrSize = 8, + unsigned char PtrAl = 8, unsigned char DoubleAl = 8, + unsigned char FloatAl = 4, unsigned char LongAl = 8, + unsigned char IntAl = 4, unsigned char ShortAl = 2, + unsigned char ByteAl = 1); + ~TargetData(); // Not virtual, do not subclass this class + + unsigned char getByteAlignment() const { return ByteAlignment; } + unsigned char getShortAlignment() const { return ShortAlignment; } + unsigned char getIntAlignment() const { return IntAlignment; } + unsigned char getLongAlignment() const { return LongAlignment; } + unsigned char getFloatAlignment() const { return FloatAlignment; } + unsigned char getDoubleAlignment() const { return DoubleAlignment; } + unsigned char getPointerAlignment() const { return PointerAlignment; } + unsigned char getPointerSize() const { return PointerSize; } + AnnotationID getStructLayoutAID() const { return AID; } + + // getTypeSize - Return the number of bytes neccesary to hold the specified + // type + unsigned getTypeSize (const Type *Ty) const; + + // getTypeAlignment - Return the minimum required alignment for the specified + // type + unsigned char getTypeAlignment(const Type *Ty) const; + + // getIndexOffset - return the offset from the beginning of the type for the + // specified indices. This is used to implement getElementPtr and load and + // stores that include the implicit form of getelementptr. + // + unsigned getIndexedOffset(const Type *Ty, + const vector &Indices) const; + + inline const StructLayout *getStructLayout(const StructType *Ty) const { + return (const StructLayout*)((const Type*)Ty)->getOrCreateAnnotation(AID); + } +}; + +// This annotation (attached ONLY to StructType classes) is used to lazily +// calculate structure layout information for a target machine, based on the +// TargetData structure. +// +struct StructLayout : public Annotation { + vector MemberOffsets; + unsigned StructSize; + unsigned StructAlignment; +private: + friend class TargetData; // Only TargetData can create this class + inline StructLayout(const StructType *ST, const TargetData &TD); +}; + +#endif diff --git a/include/llvm/Target/Machine.h b/include/llvm/Target/Machine.h new file mode 100644 index 00000000000..ae0858aff5c --- /dev/null +++ b/include/llvm/Target/Machine.h @@ -0,0 +1,780 @@ +//===-- llvm/Target/Machine.h - General Target Information -------*- C++ -*-==// +// +// This file describes the general parts of a Target machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_MACHINE_H +#define LLVM_TARGET_MACHINE_H + +#include "llvm/Target/Data.h" +#include "llvm/Support/NonCopyable.h" +#include "llvm/Support/DataTypes.h" +#include +#include +#include +#include + +class StructType; +struct MachineInstrDescriptor; +class TargetMachine; + +//--------------------------------------------------------------------------- +// Data types used to define information about a single machine instruction +//--------------------------------------------------------------------------- + +typedef int MachineOpCode; +typedef int OpCodeMask; +typedef int InstrSchedClass; + +static const unsigned MAX_OPCODE_SIZE = 16; + +typedef long long cycles_t; +const cycles_t HUGE_LATENCY = ~((unsigned long long) 1 << sizeof(cycles_t)-1); +const cycles_t INVALID_LATENCY = -HUGE_LATENCY; + + +class OpCodePair { +public: + long val; // make long by concatenating two opcodes + OpCodePair(MachineOpCode op1, MachineOpCode op2) + : val((op1 < 0 || op2 < 0)? + -1 : (long)((((unsigned) op1) << MAX_OPCODE_SIZE) | (unsigned) op2)) {} + bool operator==(const OpCodePair& op) const { + return val == op.val; + } +private: + OpCodePair(); // disable for now +}; + + +template <> struct hash { + size_t operator()(const OpCodePair& pair) const { + return hash()(pair.val); + } +}; + + +// Global variable holding an array of descriptors for machine instructions. +// The actual object needs to be created separately for each target machine. +// This variable is initialized and reset by class MachineInstrInfo. +// +extern const MachineInstrDescriptor* TargetInstrDescriptors; + + +//--------------------------------------------------------------------------- +// struct MachineInstrDescriptor: +// Predefined information about each machine instruction. +// Designed to initialized statically. +// +// class MachineInstructionInfo +// Interface to description of machine instructions +// +//--------------------------------------------------------------------------- + + +const unsigned int M_NOP_FLAG = 1; +const unsigned int M_BRANCH_FLAG = 1 << 1; +const unsigned int M_CALL_FLAG = 1 << 2; +const unsigned int M_RET_FLAG = 1 << 3; +const unsigned int M_ARITH_FLAG = 1 << 4; +const unsigned int M_CC_FLAG = 1 << 6; +const unsigned int M_LOGICAL_FLAG = 1 << 6; +const unsigned int M_INT_FLAG = 1 << 7; +const unsigned int M_FLOAT_FLAG = 1 << 8; +const unsigned int M_CONDL_FLAG = 1 << 9; +const unsigned int M_LOAD_FLAG = 1 << 10; +const unsigned int M_PREFETCH_FLAG = 1 << 11; +const unsigned int M_STORE_FLAG = 1 << 12; +const unsigned int M_DUMMY_PHI_FLAG = 1 << 13; + + +struct MachineInstrDescriptor { + string opCodeString; // Assembly language mnemonic for the opcode. + int numOperands; // Number of args; -1 if variable #args + int resultPos; // Position of the result; -1 if no result + unsigned int maxImmedConst; // Largest +ve constant in IMMMED field or 0. + bool immedIsSignExtended; // Is IMMED field sign-extended? If so, + // smallest -ve value is -(maxImmedConst+1). + unsigned int numDelaySlots; // Number of delay slots after instruction + unsigned int latency; // Latency in machine cycles + InstrSchedClass schedClass; // enum identifying instr sched class + unsigned int iclass; // flags identifying machine instr class +}; + + +class MachineInstrInfo : public NonCopyableV { +protected: + const MachineInstrDescriptor* desc; // raw array to allow static init'n + unsigned int descSize; // number of entries in the desc array + unsigned int numRealOpCodes; // number of non-dummy op codes + +public: + /*ctor*/ MachineInstrInfo(const MachineInstrDescriptor* _desc, + unsigned int _descSize, + unsigned int _numRealOpCodes); + /*dtor*/ virtual ~MachineInstrInfo(); + + unsigned int getNumRealOpCodes() const { + return numRealOpCodes; + } + + unsigned int getNumTotalOpCodes() const { + return descSize; + } + + const MachineInstrDescriptor& getDescriptor(MachineOpCode opCode) const { + assert(opCode >= 0 && opCode < (int) descSize); + return desc[opCode]; + } + + int getNumOperands (MachineOpCode opCode) const { + return getDescriptor(opCode).numOperands; + } + + int getResultPos (MachineOpCode opCode) const { + return getDescriptor(opCode).resultPos; + } + + unsigned int getNumDelaySlots(MachineOpCode opCode) const { + return getDescriptor(opCode).numDelaySlots; + } + + InstrSchedClass getSchedClass (MachineOpCode opCode) const { + return getDescriptor(opCode).schedClass; + } + + // + // Query instruction class flags according to the machine-independent + // flags listed above. + // + unsigned int getIClass (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass; + } + bool isNop (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_NOP_FLAG; + } + bool isBranch (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_BRANCH_FLAG; + } + bool isCall (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_CALL_FLAG; + } + bool isReturn (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_RET_FLAG; + } + bool isControlFlow (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_BRANCH_FLAG + || getDescriptor(opCode).iclass & M_CALL_FLAG + || getDescriptor(opCode).iclass & M_RET_FLAG; + } + bool isArith (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_RET_FLAG; + } + bool isCCInstr (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_CC_FLAG; + } + bool isLogical (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_LOGICAL_FLAG; + } + bool isIntInstr (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_INT_FLAG; + } + bool isFloatInstr (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_FLOAT_FLAG; + } + bool isConditional (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_CONDL_FLAG; + } + bool isLoad (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_LOAD_FLAG; + } + bool isPrefetch (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_PREFETCH_FLAG; + } + bool isLoadOrPrefetch (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_LOAD_FLAG + || getDescriptor(opCode).iclass & M_PREFETCH_FLAG; + } + bool isStore (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_STORE_FLAG; + } + bool isMemoryAccess (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_LOAD_FLAG + || getDescriptor(opCode).iclass & M_PREFETCH_FLAG + || getDescriptor(opCode).iclass & M_STORE_FLAG; + } + bool isDummyPhiInstr (MachineOpCode opCode) const { + return getDescriptor(opCode).iclass & M_DUMMY_PHI_FLAG; + } + + + // delete this later ******* + bool isPhi(MachineOpCode opCode) { return isDummyPhiInstr(opCode); } + + + + // Check if an instruction can be issued before its operands are ready, + // or if a subsequent instruction that uses its result can be issued + // before the results are ready. + // Default to true since most instructions on many architectures allow this. + // + virtual bool hasOperandInterlock(MachineOpCode opCode) const { + return true; + } + + virtual bool hasResultInterlock(MachineOpCode opCode) const { + return true; + } + + // + // Latencies for individual instructions and instruction pairs + // + virtual int minLatency (MachineOpCode opCode) const { + return getDescriptor(opCode).latency; + } + + virtual int maxLatency (MachineOpCode opCode) const { + return getDescriptor(opCode).latency; + } + + // Check if the specified constant fits in the immediate field + // of this machine instruction + // + virtual bool constantFitsInImmedField(MachineOpCode opCode, + int64_t intValue) const; + + // Return the largest +ve constant that can be held in the IMMMED field + // of this machine instruction. + // isSignExtended is set to true if the value is sign-extended before use + // (this is true for all immediate fields in SPARC instructions). + // Return 0 if the instruction has no IMMED field. + // + virtual uint64_t maxImmedConstant(MachineOpCode opCode, + bool& isSignExtended) const { + isSignExtended = getDescriptor(opCode).immedIsSignExtended; + return getDescriptor(opCode).maxImmedConst; + } +}; + + +//--------------------------------------------------------------------------- +// class MachineResource +// class CPUResource +// +// Purpose: +// Representation of a single machine resource used in specifying +// resource usages of machine instructions for scheduling. +//--------------------------------------------------------------------------- + + +typedef unsigned int resourceId_t; + +class MachineResource { +public: + const string rname; + resourceId_t rid; + + /*ctor*/ MachineResource(const string& resourceName) + : rname(resourceName), rid(nextId++) {} + +private: + static resourceId_t nextId; + MachineResource(); // disable +}; + + +class CPUResource : public MachineResource { +public: + int maxNumUsers; // MAXINT if no restriction + + /*ctor*/ CPUResource(const string& rname, int maxUsers) + : MachineResource(rname), maxNumUsers(maxUsers) {} +}; + + +//--------------------------------------------------------------------------- +// struct InstrClassRUsage +// struct InstrRUsageDelta +// struct InstrIssueDelta +// struct InstrRUsage +// +// Purpose: +// The first three are structures used to specify machine resource +// usages for each instruction in a machine description file: +// InstrClassRUsage : resource usages common to all instrs. in a class +// InstrRUsageDelta : add/delete resource usage for individual instrs. +// InstrIssueDelta : add/delete instr. issue info for individual instrs +// +// The last one (InstrRUsage) is the internal representation of +// instruction resource usage constructed from the above three. +//--------------------------------------------------------------------------- + +const int MAX_NUM_SLOTS = 32; +const int MAX_NUM_CYCLES = 32; + +struct InstrClassRUsage { + InstrSchedClass schedClass; + int totCycles; + + // Issue restrictions common to instructions in this class + unsigned int maxNumIssue; + bool isSingleIssue; + bool breaksGroup; + cycles_t numBubbles; + + // Feasible slots to use for instructions in this class. + // The size of vector S[] is `numSlots'. + unsigned int numSlots; + unsigned int feasibleSlots[MAX_NUM_SLOTS]; + + // Resource usages common to instructions in this class. + // The size of vector V[] is `numRUEntries'. + unsigned int numRUEntries; + struct { + resourceId_t resourceId; + unsigned int startCycle; + int numCycles; + } V[MAX_NUM_CYCLES]; +}; + +struct InstrRUsageDelta { + MachineOpCode opCode; + resourceId_t resourceId; + unsigned int startCycle; + int numCycles; +}; + +// Specify instruction issue restrictions for individual instructions +// that differ from the common rules for the class. +// +struct InstrIssueDelta { + MachineOpCode opCode; + bool isSingleIssue; + bool breaksGroup; + cycles_t numBubbles; +}; + + +struct InstrRUsage { + /*ctor*/ InstrRUsage () {} + /*ctor*/ InstrRUsage (const InstrRUsage& instrRU); + InstrRUsage& operator= (const InstrRUsage& instrRU); + + bool sameAsClass; + + // Issue restrictions for this instruction + bool isSingleIssue; + bool breaksGroup; + cycles_t numBubbles; + + // Feasible slots to use for this instruction. + vector feasibleSlots; + + // Resource usages for this instruction, with one resource vector per cycle. + cycles_t numCycles; + vector > resourcesByCycle; + +private: + // Conveniences for initializing this structure + InstrRUsage& operator= (const InstrClassRUsage& classRU); + void addIssueDelta (const InstrIssueDelta& delta); + void addUsageDelta (const InstrRUsageDelta& delta); + void setMaxSlots (int maxNumSlots); + + friend class MachineSchedInfo; // give access to these functions +}; + + +inline void +InstrRUsage::setMaxSlots(int maxNumSlots) +{ + feasibleSlots.resize(maxNumSlots); +} + +inline InstrRUsage& +InstrRUsage::operator=(const InstrRUsage& instrRU) +{ + sameAsClass = instrRU.sameAsClass; + isSingleIssue = instrRU.isSingleIssue; + breaksGroup = instrRU.breaksGroup; + numBubbles = instrRU.numBubbles; + feasibleSlots = instrRU.feasibleSlots; + numCycles = instrRU.numCycles; + resourcesByCycle = instrRU.resourcesByCycle; + return *this; +} + +inline /*ctor*/ +InstrRUsage::InstrRUsage(const InstrRUsage& instrRU) +{ + *this = instrRU; +} + +inline InstrRUsage& +InstrRUsage::operator=(const InstrClassRUsage& classRU) +{ + sameAsClass = true; + isSingleIssue = classRU.isSingleIssue; + breaksGroup = classRU.breaksGroup; + numBubbles = classRU.numBubbles; + + for (unsigned i=0; i < classRU.numSlots; i++) + { + unsigned slot = classRU.feasibleSlots[i]; + assert(slot < feasibleSlots.size() && "Invalid slot specified!"); + this->feasibleSlots[slot] = true; + } + + this->numCycles = classRU.totCycles; + this->resourcesByCycle.resize(this->numCycles); + + for (unsigned i=0; i < classRU.numRUEntries; i++) + for (unsigned c=classRU.V[i].startCycle, NC = c + classRU.V[i].numCycles; + c < NC; c++) + this->resourcesByCycle[c].push_back(classRU.V[i].resourceId); + + // Sort each resource usage vector by resourceId_t to speed up conflict checking + for (unsigned i=0; i < this->resourcesByCycle.size(); i++) + sort(resourcesByCycle[i].begin(), resourcesByCycle[i].end()); + + return *this; +} + + +inline void +InstrRUsage::addIssueDelta(const InstrIssueDelta& delta) +{ + sameAsClass = false; + isSingleIssue = delta.isSingleIssue; + breaksGroup = delta.breaksGroup; + numBubbles = delta.numBubbles; +} + + +// Add the extra resource usage requirements specified in the delta. +// Note that a negative value of `numCycles' means one entry for that +// resource should be deleted for each cycle. +// +inline void +InstrRUsage::addUsageDelta(const InstrRUsageDelta& delta) +{ + int NC = delta.numCycles; + + this->sameAsClass = false; + + // resize the resources vector if more cycles are specified + unsigned maxCycles = this->numCycles; + maxCycles = max(maxCycles, delta.startCycle + abs(NC) - 1); + if (maxCycles > this->numCycles) + { + this->resourcesByCycle.resize(maxCycles); + this->numCycles = maxCycles; + } + + if (NC >= 0) + for (unsigned c=delta.startCycle, last=c+NC-1; c <= last; c++) + this->resourcesByCycle[c].push_back(delta.resourceId); + else + // Remove the resource from all NC cycles. + for (unsigned c=delta.startCycle, last=(c-NC)-1; c <= last; c++) + { + // Look for the resource backwards so we remove the last entry + // for that resource in each cycle. + vector& rvec = this->resourcesByCycle[c]; + int r; + for (r = (int) rvec.size(); r >= 0; r--) + if (rvec[r] == delta.resourceId) + {// found last entry for the resource + rvec.erase(rvec.begin() + r); + break; + } + assert(r >= 0 && "Resource to remove was unused in cycle c!"); + } +} + + +//--------------------------------------------------------------------------- +// class MachineSchedInfo +// +// Purpose: +// Common interface to machine information for instruction scheduling +//--------------------------------------------------------------------------- + +class MachineSchedInfo : public NonCopyableV { +public: + unsigned int maxNumIssueTotal; + int longestIssueConflict; + + int branchMispredictPenalty; // 4 for SPARC IIi + int branchTargetUnknownPenalty; // 2 for SPARC IIi + int l1DCacheMissPenalty; // 7 or 9 for SPARC IIi + int l1ICacheMissPenalty; // ? for SPARC IIi + + bool inOrderLoads; // true for SPARC IIi + bool inOrderIssue; // true for SPARC IIi + bool inOrderExec; // false for most architectures + bool inOrderRetire; // true for most architectures + +protected: + inline const InstrRUsage& getInstrRUsage(MachineOpCode opCode) const { + assert(opCode >= 0 && opCode < (int) instrRUsages.size()); + return instrRUsages[opCode]; + } + inline const InstrClassRUsage& + getClassRUsage(const InstrSchedClass& sc) const { + assert(sc >= 0 && sc < numSchedClasses); + return classRUsages[sc]; + } + +public: + /*ctor*/ MachineSchedInfo (int _numSchedClasses, + const MachineInstrInfo* _mii, + const InstrClassRUsage* _classRUsages, + const InstrRUsageDelta* _usageDeltas, + const InstrIssueDelta* _issueDeltas, + unsigned int _numUsageDeltas, + unsigned int _numIssueDeltas); + /*dtor*/ virtual ~MachineSchedInfo () {} + + inline const MachineInstrInfo& getInstrInfo() const { + return *mii; + } + + inline int getNumSchedClasses() const { + return numSchedClasses; + } + + inline unsigned int getMaxNumIssueTotal() const { + return maxNumIssueTotal; + } + + inline unsigned int getMaxIssueForClass(const InstrSchedClass& sc) const { + assert(sc >= 0 && sc < numSchedClasses); + return classRUsages[sc].maxNumIssue; + } + + inline InstrSchedClass getSchedClass (MachineOpCode opCode) const { + return getInstrInfo().getSchedClass(opCode); + } + + inline bool instrCanUseSlot (MachineOpCode opCode, + unsigned s) const { + assert(s < getInstrRUsage(opCode).feasibleSlots.size() && "Invalid slot!"); + return getInstrRUsage(opCode).feasibleSlots[s]; + } + + inline int getLongestIssueConflict () const { + return longestIssueConflict; + } + + inline int getMinIssueGap (MachineOpCode fromOp, + MachineOpCode toOp) const { + hash_map::const_iterator + I = issueGaps.find(OpCodePair(fromOp, toOp)); + return (I == issueGaps.end())? 0 : (*I).second; + } + + inline const vector* + getConflictList(MachineOpCode opCode) const { + hash_map >::const_iterator + I = conflictLists.find(opCode); + return (I == conflictLists.end())? NULL : & (*I).second; + } + + inline bool isSingleIssue (MachineOpCode opCode) const { + return getInstrRUsage(opCode).isSingleIssue; + } + + inline bool breaksIssueGroup (MachineOpCode opCode) const { + return getInstrRUsage(opCode).breaksGroup; + } + + inline unsigned int numBubblesAfter (MachineOpCode opCode) const { + return getInstrRUsage(opCode).numBubbles; + } + +protected: + virtual void initializeResources (); + +private: + void computeInstrResources(const vector& instrRUForClasses); + void computeIssueGaps(const vector& instrRUForClasses); + +protected: + int numSchedClasses; + const MachineInstrInfo* mii; + const InstrClassRUsage* classRUsages; // raw array by sclass + const InstrRUsageDelta* usageDeltas; // raw array [1:numUsageDeltas] + const InstrIssueDelta* issueDeltas; // raw array [1:numIssueDeltas] + unsigned int numUsageDeltas; + unsigned int numIssueDeltas; + + vector instrRUsages; // indexed by opcode + hash_map issueGaps; // indexed by opcode pair + hash_map > + conflictLists; // indexed by opcode +}; + + + +//----------------------------------------------------------------------------- +// class MachineRegClassInfo +// +// Purpose: +// Interface to description of machine register class (e.g., int reg class +// float reg class etc) +// +//-------------------------------------------------------------------------- + +class IGNode; + + +class MachineRegClassInfo { + +protected: + + const unsigned RegClassID; // integer ID of a reg class + const unsigned NumOfAvailRegs; // # of avail for coloring -without SP etc. + const unsigned NumOfAllRegs; // # of all registers -including SP,g0 etc. + +public: + + inline unsigned getRegClassID() const { return RegClassID; } + inline unsigned getNumOfAvailRegs() const { return NumOfAvailRegs; } + inline unsigned getNumOfAllRegs() const { return NumOfAllRegs; } + + + + // This method should find a color which is not used by neighbors + // (i.e., a false position in IsColorUsedArr) and + virtual void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const = 0; + + + MachineRegClassInfo(const unsigned ID, const unsigned NVR, + const unsigned NAR): RegClassID(ID), NumOfAvailRegs(NVR), + NumOfAllRegs(NAR) + { } // empty constructor + +}; + + + + +//--------------------------------------------------------------------------- +// class MachineRegInfo +// +// Purpose: +// Interface to register info of target machine +// +//-------------------------------------------------------------------------- + +class LiveRangeInfo; +class Method; +class Instruction; +class LiveRange; +class AddedInstrns; +class MachineInstr; +typedef hash_map AddedInstrMapType; + +// A vector of all machine register classes +typedef vector MachineRegClassArrayType; + + +class MachineRegInfo : public NonCopyableV { + +protected: + + MachineRegClassArrayType MachineRegClassArr; + + +public: + + + inline unsigned int getNumOfRegClasses() const { + return MachineRegClassArr.size(); + } + + const MachineRegClassInfo *const getMachineRegClass(unsigned i) const { + return MachineRegClassArr[i]; + } + + + virtual unsigned getRegClassIDOfValue (const Value *const Val) const = 0; + + virtual void colorArgs(const Method *const Meth, + LiveRangeInfo & LRI) const = 0; + + virtual void colorCallArgs(vector & CallInstrList, + LiveRangeInfo& LRI, + AddedInstrMapType& AddedInstrMap ) const = 0; + + virtual int getUnifiedRegNum(int RegClassID, int reg) const = 0; + + virtual const string getUnifiedRegName(int reg) const = 0; + + //virtual void printReg(const LiveRange *const LR) const =0; + + MachineRegInfo() { } + +}; + + + + + +//--------------------------------------------------------------------------- +// class TargetMachine +// +// Purpose: +// Primary interface to machine description for the target machine. +// +//--------------------------------------------------------------------------- + +class TargetMachine : public NonCopyableV { +public: + const string TargetName; + const TargetData DataLayout; // Calculates type size & alignment + int optSizeForSubWordData; + int minMemOpWordSize; + int maxAtomicMemOpWordSize; + + // Register information. This needs to be reorganized into a single class. + int zeroRegNum; // register that gives 0 if any (-1 if none) + +public: + TargetMachine(const string &targetname, + unsigned char PtrSize = 8, unsigned char PtrAl = 8, + unsigned char DoubleAl = 8, unsigned char FloatAl = 4, + unsigned char LongAl = 8, unsigned char IntAl = 4, + unsigned char ShortAl = 2, unsigned char ByteAl = 1) + : TargetName(targetname), DataLayout(targetname, PtrSize, PtrAl, + DoubleAl, FloatAl, LongAl, IntAl, + ShortAl, ByteAl) { } + virtual ~TargetMachine() {} + + virtual const MachineInstrInfo& getInstrInfo() const = 0; + + virtual unsigned int findOptimalStorageSize (const Type* ty) const; + + // This really should be in the register info class + virtual bool regsMayBeAliased (unsigned int regNum1, + unsigned int regNum2) const { + return (regNum1 == regNum2); + } + + // compileMethod - This does everything neccesary to compile a method into the + // built in representation. This allows the target to have complete control + // over how it does compilation. This does not emit assembly or output + // machine code however, this is done later. + // + virtual bool compileMethod(Method *M) = 0; + + // emitAssembly - Output assembly language code (a .s file) for the specified + // method. The specified method must have been compiled before this may be + // used. + // + virtual void emitAssembly(Method *M, ostream &OutStr) { /* todo */ } +}; + +#endif diff --git a/include/llvm/Target/Sparc.h b/include/llvm/Target/Sparc.h new file mode 100644 index 00000000000..83bebbddaf3 --- /dev/null +++ b/include/llvm/Target/Sparc.h @@ -0,0 +1,17 @@ +//===-- llvm/CodeGen/Sparc.h - Sparc Target Description ----------*- C++ -*--=// +// +// This file defines the Sparc processor targets +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SPARC_H +#define LLVM_CODEGEN_SPARC_H + +class TargetMachine; + +// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine +// that implements the Sparc backend. +// +TargetMachine *allocateSparcTargetMachine(); + +#endif diff --git a/include/llvm/Target/TargetMachineImpls.h b/include/llvm/Target/TargetMachineImpls.h new file mode 100644 index 00000000000..83bebbddaf3 --- /dev/null +++ b/include/llvm/Target/TargetMachineImpls.h @@ -0,0 +1,17 @@ +//===-- llvm/CodeGen/Sparc.h - Sparc Target Description ----------*- C++ -*--=// +// +// This file defines the Sparc processor targets +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SPARC_H +#define LLVM_CODEGEN_SPARC_H + +class TargetMachine; + +// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine +// that implements the Sparc backend. +// +TargetMachine *allocateSparcTargetMachine(); + +#endif diff --git a/lib/CodeGen/InstrSched/InstrScheduling.cpp b/lib/CodeGen/InstrSched/InstrScheduling.cpp index 23586870655..0987572ac3f 100644 --- a/lib/CodeGen/InstrSched/InstrScheduling.cpp +++ b/lib/CodeGen/InstrSched/InstrScheduling.cpp @@ -12,7 +12,7 @@ #include "llvm/CodeGen/InstrScheduling.h" #include "llvm/CodeGen/SchedPriorities.h" #include "llvm/Analysis/LiveVar/BBLiveVar.h" -#include "llvm/CodeGen/TargetMachine.h" +#include "llvm/Target/Machine.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Instruction.h" diff --git a/lib/CodeGen/InstrSched/SchedGraph.cpp b/lib/CodeGen/InstrSched/SchedGraph.cpp index 05109cb8526..3c819f6bc7d 100644 --- a/lib/CodeGen/InstrSched/SchedGraph.cpp +++ b/lib/CodeGen/InstrSched/SchedGraph.cpp @@ -18,7 +18,7 @@ #include "llvm/Method.h" #include "llvm/CodeGen/SchedGraph.h" #include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/TargetMachine.h" +#include "llvm/Target/Machine.h" #include "llvm/Support/StringExtras.h" #include diff --git a/lib/CodeGen/Makefile b/lib/CodeGen/Makefile index 1c0e390088a..b0fba9d6567 100644 --- a/lib/CodeGen/Makefile +++ b/lib/CodeGen/Makefile @@ -1,4 +1,4 @@ LEVEL = ../.. -DIRS = TargetMachine InstrSelection InstrSched +DIRS = InstrSelection InstrSched include $(LEVEL)/Makefile.common diff --git a/lib/CodeGen/RegAlloc/RegClass.h b/lib/CodeGen/RegAlloc/RegClass.h index 1d08502445d..efe174617ce 100644 --- a/lib/CodeGen/RegAlloc/RegClass.h +++ b/lib/CodeGen/RegAlloc/RegClass.h @@ -16,19 +16,14 @@ */ - - #ifndef REG_CLASS_H #define REG_CLASS_H #include "llvm/CodeGen/IGNode.h" #include "llvm/CodeGen/InterferenceGraph.h" -#include "llvm/CodeGen/TargetMachine.h" - - +#include "llvm/Target/Machine.h" #include - typedef vector ReservedColorListType; diff --git a/lib/CodeGen/TargetMachine/Makefile b/lib/CodeGen/TargetMachine/Makefile deleted file mode 100644 index eefef8907a9..00000000000 --- a/lib/CodeGen/TargetMachine/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -LEVEL = ../../.. - -LIBRARYNAME = target - -include $(LEVEL)/Makefile.common diff --git a/lib/CodeGen/TargetMachine/TargetData.cpp b/lib/CodeGen/TargetMachine/TargetData.cpp deleted file mode 100644 index fd9dd26d282..00000000000 --- a/lib/CodeGen/TargetMachine/TargetData.cpp +++ /dev/null @@ -1,180 +0,0 @@ -//===-- TargetData.cpp - Data size & alignment routines --------------------==// -// -// This file defines target properties related to datatype size/offset/alignment -// information. It uses lazy annotations to cache information about how -// structure types are laid out and used. -// -// This structure should be created once, filled in if the defaults are not -// correct and then passed around by const&. None of the members functions -// require modification to the object. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/TargetData.h" -#include "llvm/DerivedTypes.h" -#include "llvm/ConstPoolVals.h" - -static inline void getTypeInfo(const Type *Ty, const TargetData *TD, - unsigned &Size, unsigned char &Alignment); - -//===----------------------------------------------------------------------===// -// Support for StructLayout Annotation -//===----------------------------------------------------------------------===// - -StructLayout::StructLayout(const StructType *ST, const TargetData &TD) - : Annotation(TD.getStructLayoutAID()) { - StructAlignment = 0; - StructSize = 0; - - // Loop over each of the elements, placing them in memory... - for (StructType::ElementTypes::const_iterator - TI = ST->getElementTypes().begin(), - TE = ST->getElementTypes().end(); TI != TE; ++TI) { - const Type *Ty = *TI; - unsigned char A; - unsigned TySize, TyAlign; - getTypeInfo(Ty, &TD, TySize, A); TyAlign = A; - - // Add padding if neccesary to make the data element aligned properly... - if (StructSize % TyAlign != 0) - StructSize = (StructSize/TyAlign + 1) * TyAlign; // Add padding... - - // Keep track of maximum alignment constraint - StructAlignment = max(TyAlign, StructAlignment); - - MemberOffsets.push_back(StructSize); - StructSize += TySize; // Consume space for this data item... - } - - // Add padding to the end of the struct so that it could be put in an array - // and all array elements would be aligned correctly. - if (StructSize % StructAlignment != 0) - StructSize = (StructSize/StructAlignment + 1) * StructAlignment; - - if (StructSize == 0) { - StructSize = 1; // Empty struct is 1 byte - StructAlignment = 1; - } -} - -Annotation *TargetData::TypeAnFactory(AnnotationID AID, const Annotable *T, - void *D) { - const TargetData &TD = *(const TargetData*)D; - assert(AID == TD.AID && "Target data annotation ID mismatch!"); - const Type *Ty = ((const Value *)T)->castTypeAsserting(); - assert(Ty->isStructType() && - "Can only create StructLayout annotation on structs!"); - return new StructLayout((const StructType *)Ty, TD); -} - -//===----------------------------------------------------------------------===// -// TargetData Class Implementation -//===----------------------------------------------------------------------===// - -TargetData::TargetData(const string &TargetName, unsigned char PtrSize = 8, - unsigned char PtrAl = 8, unsigned char DoubleAl = 8, - unsigned char FloatAl = 4, unsigned char LongAl = 8, - unsigned char IntAl = 4, unsigned char ShortAl = 2, - unsigned char ByteAl = 1) - : AID(AnnotationManager::getID("TargetData::" + TargetName)) { - AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this); - - PointerSize = PtrSize; - PointerAlignment = PtrAl; - DoubleAlignment = DoubleAl; - FloatAlignment = FloatAl; - LongAlignment = LongAl; - IntAlignment = IntAl; - ShortAlignment = ShortAl; - ByteAlignment = ByteAl; -} - -TargetData::~TargetData() { - AnnotationManager::registerAnnotationFactory(AID, 0); // Deregister factory -} - -static inline void getTypeInfo(const Type *Ty, const TargetData *TD, - unsigned &Size, unsigned char &Alignment) { - switch (Ty->getPrimitiveID()) { - case Type::VoidTyID: - case Type::BoolTyID: - case Type::UByteTyID: - case Type::SByteTyID: Size = 1; Alignment = TD->getByteAlignment(); return; - case Type::UShortTyID: - case Type::ShortTyID: Size = 2; Alignment = TD->getShortAlignment(); return; - case Type::UIntTyID: - case Type::IntTyID: Size = 4; Alignment = TD->getIntAlignment(); return; - case Type::ULongTyID: - case Type::LongTyID: Size = 8; Alignment = TD->getLongAlignment(); return; - case Type::FloatTyID: Size = 4; Alignment = TD->getFloatAlignment(); return; - case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return; - case Type::LabelTyID: - case Type::PointerTyID: - Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment(); - return; - case Type::ArrayTyID: { - const ArrayType *ATy = (const ArrayType *)Ty; - assert(ATy->isSized() && "Can't get TypeInfo of an unsized array!"); - getTypeInfo(ATy->getElementType(), TD, Size, Alignment); - Size *= ATy->getNumElements(); - return; - } - case Type::StructTyID: { - // Get the layout annotation... which is lazily created on demand. - const StructLayout *Layout = TD->getStructLayout((const StructType*)Ty); - Size = Layout->StructSize; Alignment = Layout->StructAlignment; - return; - } - - case Type::TypeTyID: - default: - assert(0 && "Bad type for getTypeInfo!!!"); - return; - } -} - -unsigned TargetData::getTypeSize(const Type *Ty) const { - unsigned Size; unsigned char Align; - getTypeInfo(Ty, this, Size, Align); - return Size; -} - -unsigned char TargetData::getTypeAlignment(const Type *Ty) const { - unsigned Size; unsigned char Align; - getTypeInfo(Ty, this, Size, Align); - return Align; -} - -unsigned TargetData::getIndexedOffset(const Type *ptrTy, - const vector &Idx) const { - const PointerType *PtrTy = ptrTy->castPointerType(); - unsigned Result = 0; - - // Get the type pointed to... - const Type *Ty = PtrTy->getValueType(); - - for (unsigned CurIDX = 0; CurIDX < Idx.size(); ++CurIDX) { - if (const StructType *STy = Ty->dyncastStructType()) { - assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx"); - unsigned FieldNo = ((ConstPoolUInt*)Idx[CurIDX++])->getValue(); - - // Get structure layout information... - const StructLayout *Layout = getStructLayout(STy); - - // Add in the offset, as calculated by the structure layout info... - assert(FieldNo < Layout->MemberOffsets.size() && "FieldNo out of range!"); - Result += Layout->MemberOffsets[FieldNo]; - - // Update Ty to refer to current element - Ty = STy->getElementTypes()[FieldNo]; - - } else if (const ArrayType *ATy = Ty->dyncastArrayType()) { - assert(0 && "Loading from arrays not implemented yet!"); - } else { - assert(0 && "Indexing type that is not struct or array?"); - return 0; // Load directly through ptr - } - } - - return Result; -} diff --git a/lib/CodeGen/TargetMachine/TargetMachine.cpp b/lib/CodeGen/TargetMachine/TargetMachine.cpp deleted file mode 100644 index 0a9a739071b..00000000000 --- a/lib/CodeGen/TargetMachine/TargetMachine.cpp +++ /dev/null @@ -1,295 +0,0 @@ -// $Id$ -//*************************************************************************** -// File: -// TargetMachine.cpp -// -// Purpose: -// -// History: -// 7/12/01 - Vikram Adve - Created -//**************************************************************************/ - - -//*************************** User Include Files ***************************/ - -#include "llvm/CodeGen/TargetMachine.h" -#include "llvm/DerivedTypes.h" - -//************************ Exported Constants ******************************/ - - -// External object describing the machine instructions -// Initialized only when the TargetMachine class is created -// and reset when that class is destroyed. -// -const MachineInstrDescriptor* TargetInstrDescriptors = NULL; - -resourceId_t MachineResource::nextId = 0; - -//************************* Forward Declarations **************************/ - -static cycles_t ComputeMinGap (const InstrRUsage& fromRU, - const InstrRUsage& toRU); - -static bool RUConflict (const vector& fromRVec, - const vector& fromRVec); - - -//************************ Class Implementations **************************/ - -//--------------------------------------------------------------------------- -// class TargetMachine -// -// Purpose: -// Machine description. -// -//--------------------------------------------------------------------------- - - -// function TargetMachine::findOptimalStorageSize -// -// Purpose: -// This default implementation assumes that all sub-word data items use -// space equal to optSizeForSubWordData, and all other primitive data -// items use space according to the type. -// -unsigned int TargetMachine::findOptimalStorageSize(const Type* ty) const { - switch(ty->getPrimitiveID()) { - case Type::BoolTyID: - case Type::UByteTyID: - case Type::SByteTyID: - case Type::UShortTyID: - case Type::ShortTyID: - return optSizeForSubWordData; - - default: - return DataLayout.getTypeSize(ty); - } -} - - -//--------------------------------------------------------------------------- -// class MachineInstructionInfo -// Interface to description of machine instructions -//--------------------------------------------------------------------------- - - -/*ctor*/ -MachineInstrInfo::MachineInstrInfo(const MachineInstrDescriptor* _desc, - unsigned int _descSize, - unsigned int _numRealOpCodes) - : desc(_desc), descSize(_descSize), numRealOpCodes(_numRealOpCodes) -{ - assert(TargetInstrDescriptors == NULL && desc != NULL); - TargetInstrDescriptors = desc; // initialize global variable -} - - -/*dtor*/ -MachineInstrInfo::~MachineInstrInfo() -{ - TargetInstrDescriptors = NULL; // reset global variable -} - - -bool -MachineInstrInfo::constantFitsInImmedField(MachineOpCode opCode, - int64_t intValue) const -{ - // First, check if opCode has an immed field. - bool isSignExtended; - uint64_t maxImmedValue = this->maxImmedConstant(opCode, isSignExtended); - if (maxImmedValue != 0) - { - // Now check if the constant fits - if (intValue <= (int64_t) maxImmedValue && - intValue >= -((int64_t) maxImmedValue+1)) - return true; - } - - return false; -} - - -//--------------------------------------------------------------------------- -// class MachineSchedInfo -// Interface to machine description for instruction scheduling -//--------------------------------------------------------------------------- - -/*ctor*/ -MachineSchedInfo::MachineSchedInfo(int _numSchedClasses, - const MachineInstrInfo* _mii, - const InstrClassRUsage* _classRUsages, - const InstrRUsageDelta* _usageDeltas, - const InstrIssueDelta* _issueDeltas, - unsigned int _numUsageDeltas, - unsigned int _numIssueDeltas) - : numSchedClasses(_numSchedClasses), - mii(_mii), - classRUsages(_classRUsages), - usageDeltas(_usageDeltas), - issueDeltas(_issueDeltas), - numUsageDeltas(_numUsageDeltas), - numIssueDeltas(_numIssueDeltas) -{ -} - -void -MachineSchedInfo::initializeResources() -{ - assert(MAX_NUM_SLOTS >= (int) getMaxNumIssueTotal() - && "Insufficient slots for static data! Increase MAX_NUM_SLOTS"); - - // First, compute common resource usage info for each class because - // most instructions will probably behave the same as their class. - // Cannot allocate a vector of InstrRUsage so new each one. - // - vector instrRUForClasses; - instrRUForClasses.resize(numSchedClasses); - for (InstrSchedClass sc=0; sc < numSchedClasses; sc++) - { - // instrRUForClasses.push_back(new InstrRUsage); - instrRUForClasses[sc].setMaxSlots(getMaxNumIssueTotal()); - instrRUForClasses[sc] = classRUsages[sc]; - } - - computeInstrResources(instrRUForClasses); - - computeIssueGaps(instrRUForClasses); -} - - -void -MachineSchedInfo::computeInstrResources(const vector& instrRUForClasses) -{ - int numOpCodes = mii->getNumRealOpCodes(); - instrRUsages.resize(numOpCodes); - - // First get the resource usage information from the class resource usages. - for (MachineOpCode op=0; op < numOpCodes; op++) - { - InstrSchedClass sc = getSchedClass(op); - assert(sc >= 0 && sc < numSchedClasses); - instrRUsages[op] = instrRUForClasses[sc]; - } - - // Now, modify the resource usages as specified in the deltas. - for (unsigned i=0; i < numUsageDeltas; i++) - { - MachineOpCode op = usageDeltas[i].opCode; - assert(op < numOpCodes); - instrRUsages[op].addUsageDelta(usageDeltas[i]); - } - - // Then modify the issue restrictions as specified in the deltas. - for (unsigned i=0; i < numIssueDeltas; i++) - { - MachineOpCode op = issueDeltas[i].opCode; - assert(op < numOpCodes); - instrRUsages[issueDeltas[i].opCode].addIssueDelta(issueDeltas[i]); - } -} - - -void -MachineSchedInfo::computeIssueGaps(const vector& instrRUForClasses) -{ - int numOpCodes = mii->getNumRealOpCodes(); - instrRUsages.resize(numOpCodes); - - assert(numOpCodes < (1 << MAX_OPCODE_SIZE) - 1 - && "numOpCodes invalid for implementation of class OpCodePair!"); - - // First, compute issue gaps between pairs of classes based on common - // resources usages for each class, because most instruction pairs will - // usually behave the same as their class. - // - int classPairGaps[numSchedClasses][numSchedClasses]; - for (InstrSchedClass fromSC=0; fromSC < numSchedClasses; fromSC++) - for (InstrSchedClass toSC=0; toSC < numSchedClasses; toSC++) - { - int classPairGap = ComputeMinGap(instrRUForClasses[fromSC], - instrRUForClasses[toSC]); - classPairGaps[fromSC][toSC] = classPairGap; - } - - // Now, for each pair of instructions, use the class pair gap if both - // instructions have identical resource usage as their respective classes. - // If not, recompute the gap for the pair from scratch. - - longestIssueConflict = 0; - - for (MachineOpCode fromOp=0; fromOp < numOpCodes; fromOp++) - for (MachineOpCode toOp=0; toOp < numOpCodes; toOp++) - { - int instrPairGap = - (instrRUsages[fromOp].sameAsClass && instrRUsages[toOp].sameAsClass) - ? classPairGaps[getSchedClass(fromOp)][getSchedClass(toOp)] - : ComputeMinGap(instrRUsages[fromOp], instrRUsages[toOp]); - - if (instrPairGap > 0) - { - issueGaps[OpCodePair(fromOp,toOp)] = instrPairGap; - conflictLists[fromOp].push_back(toOp); - longestIssueConflict = max(longestIssueConflict, instrPairGap); - } - } -} - - -// Check if fromRVec and toRVec have *any* common entries. -// Assume the vectors are sorted in increasing order. -// Algorithm copied from function set_intersection() for sorted ranges (stl_algo.h). -inline static bool -RUConflict(const vector& fromRVec, - const vector& toRVec) -{ - bool commonElementFound = false; - - unsigned fN = fromRVec.size(), tN = toRVec.size(); - unsigned fi = 0, ti = 0; - while (fi < fN && ti < tN) - if (fromRVec[fi] < toRVec[ti]) - ++fi; - else if (toRVec[ti] < fromRVec[fi]) - ++ti; - else - { - commonElementFound = true; - break; - } - - return commonElementFound; -} - - -static cycles_t -ComputeMinGap(const InstrRUsage& fromRU, const InstrRUsage& toRU) -{ - cycles_t minGap = 0; - - if (fromRU.numBubbles > 0) - minGap = fromRU.numBubbles; - - if (minGap < fromRU.numCycles) - { - // only need to check from cycle `minGap' onwards - for (cycles_t gap=minGap; gap <= fromRU.numCycles-1; gap++) - { - // check if instr. #2 can start executing `gap' cycles after #1 - // by checking for resource conflicts in each overlapping cycle - cycles_t numOverlap = min(fromRU.numCycles - gap, toRU.numCycles); - for (cycles_t c = 0; c <= numOverlap-1; c++) - if (RUConflict(fromRU.resourcesByCycle[gap + c], - toRU.resourcesByCycle[c])) - {// conflict found so minGap must be more than `gap' - minGap = gap+1; - break; - } - } - } - - return minGap; -} - -//--------------------------------------------------------------------------- diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 0b017ad574a..ff914106643 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -13,7 +13,7 @@ #include "llvm/ConstPoolVals.h" #include "llvm/Assembly/Writer.h" #include "llvm/Support/DataTypes.h" -#include "llvm/CodeGen/TargetData.h" +#include "llvm/Target/Data.h" static unsigned getOperandSlot(Value *V) { SlotNumber *SN = (SlotNumber*)V->getAnnotation(SlotNumberAID); diff --git a/lib/Target/Makefile b/lib/Target/Makefile index ebcd23a242f..7fd02c66722 100644 --- a/lib/Target/Makefile +++ b/lib/Target/Makefile @@ -1,5 +1,5 @@ LEVEL = ../.. DIRS = Sparc +LIBRARYNAME = target include $(LEVEL)/Makefile.common - diff --git a/lib/Target/SparcV9/InstrSched/InstrScheduling.cpp b/lib/Target/SparcV9/InstrSched/InstrScheduling.cpp index 23586870655..0987572ac3f 100644 --- a/lib/Target/SparcV9/InstrSched/InstrScheduling.cpp +++ b/lib/Target/SparcV9/InstrSched/InstrScheduling.cpp @@ -12,7 +12,7 @@ #include "llvm/CodeGen/InstrScheduling.h" #include "llvm/CodeGen/SchedPriorities.h" #include "llvm/Analysis/LiveVar/BBLiveVar.h" -#include "llvm/CodeGen/TargetMachine.h" +#include "llvm/Target/Machine.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Instruction.h" diff --git a/lib/Target/SparcV9/InstrSched/SchedGraph.cpp b/lib/Target/SparcV9/InstrSched/SchedGraph.cpp index 05109cb8526..3c819f6bc7d 100644 --- a/lib/Target/SparcV9/InstrSched/SchedGraph.cpp +++ b/lib/Target/SparcV9/InstrSched/SchedGraph.cpp @@ -18,7 +18,7 @@ #include "llvm/Method.h" #include "llvm/CodeGen/SchedGraph.h" #include "llvm/CodeGen/MachineInstr.h" -#include "llvm/CodeGen/TargetMachine.h" +#include "llvm/Target/Machine.h" #include "llvm/Support/StringExtras.h" #include diff --git a/lib/Target/SparcV9/RegAlloc/RegClass.h b/lib/Target/SparcV9/RegAlloc/RegClass.h index 1d08502445d..efe174617ce 100644 --- a/lib/Target/SparcV9/RegAlloc/RegClass.h +++ b/lib/Target/SparcV9/RegAlloc/RegClass.h @@ -16,19 +16,14 @@ */ - - #ifndef REG_CLASS_H #define REG_CLASS_H #include "llvm/CodeGen/IGNode.h" #include "llvm/CodeGen/InterferenceGraph.h" -#include "llvm/CodeGen/TargetMachine.h" - - +#include "llvm/Target/Machine.h" #include - typedef vector ReservedColorListType; diff --git a/lib/Target/SparcV9/SparcV9Internals.h b/lib/Target/SparcV9/SparcV9Internals.h index 606966db731..f9a344b37af 100644 --- a/lib/Target/SparcV9/SparcV9Internals.h +++ b/lib/Target/SparcV9/SparcV9Internals.h @@ -8,7 +8,7 @@ #ifndef SPARC_INTERNALS_H #define SPARC_INTERNALS_H -#include "llvm/CodeGen/TargetMachine.h" +#include "llvm/Target/Machine.h" #include "SparcRegInfo.h" #include diff --git a/lib/Target/SparcV9/SparcV9RegInfo.h b/lib/Target/SparcV9/SparcV9RegInfo.h index 41a6d00a081..3ebef550f08 100644 --- a/lib/Target/SparcV9/SparcV9RegInfo.h +++ b/lib/Target/SparcV9/SparcV9RegInfo.h @@ -4,19 +4,17 @@ Purpose: Contains the description of integer register class of Sparc */ - #ifndef SPARC_INT_REG_CLASS_H #define SPARC_INT_REG_CLASS_H -#include "llvm/CodeGen/TargetMachine.h" +#include "llvm/Target/Machine.h" //----------------------------------------------------------------------------- // Integer Register Class //----------------------------------------------------------------------------- - // Int register names in same order as enum in class SparcIntRegOrder - +// static string const IntRegNames[] = { "g1", "g2", "g3", "g4", "g5", "g6", "g7", "o0", "o1", "o2", "o3", "o4", "o5", "o7", diff --git a/lib/Target/TargetData.cpp b/lib/Target/TargetData.cpp new file mode 100644 index 00000000000..2e2ffd84cd1 --- /dev/null +++ b/lib/Target/TargetData.cpp @@ -0,0 +1,180 @@ +//===-- TargetData.cpp - Data size & alignment routines --------------------==// +// +// This file defines target properties related to datatype size/offset/alignment +// information. It uses lazy annotations to cache information about how +// structure types are laid out and used. +// +// This structure should be created once, filled in if the defaults are not +// correct and then passed around by const&. None of the members functions +// require modification to the object. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/Data.h" +#include "llvm/DerivedTypes.h" +#include "llvm/ConstPoolVals.h" + +static inline void getTypeInfo(const Type *Ty, const TargetData *TD, + unsigned &Size, unsigned char &Alignment); + +//===----------------------------------------------------------------------===// +// Support for StructLayout Annotation +//===----------------------------------------------------------------------===// + +StructLayout::StructLayout(const StructType *ST, const TargetData &TD) + : Annotation(TD.getStructLayoutAID()) { + StructAlignment = 0; + StructSize = 0; + + // Loop over each of the elements, placing them in memory... + for (StructType::ElementTypes::const_iterator + TI = ST->getElementTypes().begin(), + TE = ST->getElementTypes().end(); TI != TE; ++TI) { + const Type *Ty = *TI; + unsigned char A; + unsigned TySize, TyAlign; + getTypeInfo(Ty, &TD, TySize, A); TyAlign = A; + + // Add padding if neccesary to make the data element aligned properly... + if (StructSize % TyAlign != 0) + StructSize = (StructSize/TyAlign + 1) * TyAlign; // Add padding... + + // Keep track of maximum alignment constraint + StructAlignment = max(TyAlign, StructAlignment); + + MemberOffsets.push_back(StructSize); + StructSize += TySize; // Consume space for this data item... + } + + // Add padding to the end of the struct so that it could be put in an array + // and all array elements would be aligned correctly. + if (StructSize % StructAlignment != 0) + StructSize = (StructSize/StructAlignment + 1) * StructAlignment; + + if (StructSize == 0) { + StructSize = 1; // Empty struct is 1 byte + StructAlignment = 1; + } +} + +Annotation *TargetData::TypeAnFactory(AnnotationID AID, const Annotable *T, + void *D) { + const TargetData &TD = *(const TargetData*)D; + assert(AID == TD.AID && "Target data annotation ID mismatch!"); + const Type *Ty = ((const Value *)T)->castTypeAsserting(); + assert(Ty->isStructType() && + "Can only create StructLayout annotation on structs!"); + return new StructLayout((const StructType *)Ty, TD); +} + +//===----------------------------------------------------------------------===// +// TargetData Class Implementation +//===----------------------------------------------------------------------===// + +TargetData::TargetData(const string &TargetName, unsigned char PtrSize = 8, + unsigned char PtrAl = 8, unsigned char DoubleAl = 8, + unsigned char FloatAl = 4, unsigned char LongAl = 8, + unsigned char IntAl = 4, unsigned char ShortAl = 2, + unsigned char ByteAl = 1) + : AID(AnnotationManager::getID("TargetData::" + TargetName)) { + AnnotationManager::registerAnnotationFactory(AID, TypeAnFactory, this); + + PointerSize = PtrSize; + PointerAlignment = PtrAl; + DoubleAlignment = DoubleAl; + FloatAlignment = FloatAl; + LongAlignment = LongAl; + IntAlignment = IntAl; + ShortAlignment = ShortAl; + ByteAlignment = ByteAl; +} + +TargetData::~TargetData() { + AnnotationManager::registerAnnotationFactory(AID, 0); // Deregister factory +} + +static inline void getTypeInfo(const Type *Ty, const TargetData *TD, + unsigned &Size, unsigned char &Alignment) { + switch (Ty->getPrimitiveID()) { + case Type::VoidTyID: + case Type::BoolTyID: + case Type::UByteTyID: + case Type::SByteTyID: Size = 1; Alignment = TD->getByteAlignment(); return; + case Type::UShortTyID: + case Type::ShortTyID: Size = 2; Alignment = TD->getShortAlignment(); return; + case Type::UIntTyID: + case Type::IntTyID: Size = 4; Alignment = TD->getIntAlignment(); return; + case Type::ULongTyID: + case Type::LongTyID: Size = 8; Alignment = TD->getLongAlignment(); return; + case Type::FloatTyID: Size = 4; Alignment = TD->getFloatAlignment(); return; + case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return; + case Type::LabelTyID: + case Type::PointerTyID: + Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment(); + return; + case Type::ArrayTyID: { + const ArrayType *ATy = (const ArrayType *)Ty; + assert(ATy->isSized() && "Can't get TypeInfo of an unsized array!"); + getTypeInfo(ATy->getElementType(), TD, Size, Alignment); + Size *= ATy->getNumElements(); + return; + } + case Type::StructTyID: { + // Get the layout annotation... which is lazily created on demand. + const StructLayout *Layout = TD->getStructLayout((const StructType*)Ty); + Size = Layout->StructSize; Alignment = Layout->StructAlignment; + return; + } + + case Type::TypeTyID: + default: + assert(0 && "Bad type for getTypeInfo!!!"); + return; + } +} + +unsigned TargetData::getTypeSize(const Type *Ty) const { + unsigned Size; unsigned char Align; + getTypeInfo(Ty, this, Size, Align); + return Size; +} + +unsigned char TargetData::getTypeAlignment(const Type *Ty) const { + unsigned Size; unsigned char Align; + getTypeInfo(Ty, this, Size, Align); + return Align; +} + +unsigned TargetData::getIndexedOffset(const Type *ptrTy, + const vector &Idx) const { + const PointerType *PtrTy = ptrTy->castPointerType(); + unsigned Result = 0; + + // Get the type pointed to... + const Type *Ty = PtrTy->getValueType(); + + for (unsigned CurIDX = 0; CurIDX < Idx.size(); ++CurIDX) { + if (const StructType *STy = Ty->dyncastStructType()) { + assert(Idx[CurIDX]->getType() == Type::UByteTy && "Illegal struct idx"); + unsigned FieldNo = ((ConstPoolUInt*)Idx[CurIDX++])->getValue(); + + // Get structure layout information... + const StructLayout *Layout = getStructLayout(STy); + + // Add in the offset, as calculated by the structure layout info... + assert(FieldNo < Layout->MemberOffsets.size() && "FieldNo out of range!"); + Result += Layout->MemberOffsets[FieldNo]; + + // Update Ty to refer to current element + Ty = STy->getElementTypes()[FieldNo]; + + } else if (const ArrayType *ATy = Ty->dyncastArrayType()) { + assert(0 && "Loading from arrays not implemented yet!"); + } else { + assert(0 && "Indexing type that is not struct or array?"); + return 0; // Load directly through ptr + } + } + + return Result; +} diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp new file mode 100644 index 00000000000..a9e376e10a9 --- /dev/null +++ b/lib/Target/TargetMachine.cpp @@ -0,0 +1,279 @@ +//===-- TargetMachine.cpp - General Target Information ---------------------==// +// +// This file describes the general parts of a Target machine. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/Machine.h" +#include "llvm/DerivedTypes.h" + +// External object describing the machine instructions +// Initialized only when the TargetMachine class is created +// and reset when that class is destroyed. +// +const MachineInstrDescriptor* TargetInstrDescriptors = NULL; + +resourceId_t MachineResource::nextId = 0; + +static cycles_t ComputeMinGap (const InstrRUsage& fromRU, + const InstrRUsage& toRU); + +static bool RUConflict (const vector& fromRVec, + const vector& fromRVec); + +//--------------------------------------------------------------------------- +// class TargetMachine +// +// Purpose: +// Machine description. +// +//--------------------------------------------------------------------------- + + +// function TargetMachine::findOptimalStorageSize +// +// Purpose: +// This default implementation assumes that all sub-word data items use +// space equal to optSizeForSubWordData, and all other primitive data +// items use space according to the type. +// +unsigned int TargetMachine::findOptimalStorageSize(const Type* ty) const { + switch(ty->getPrimitiveID()) { + case Type::BoolTyID: + case Type::UByteTyID: + case Type::SByteTyID: + case Type::UShortTyID: + case Type::ShortTyID: + return optSizeForSubWordData; + + default: + return DataLayout.getTypeSize(ty); + } +} + + +//--------------------------------------------------------------------------- +// class MachineInstructionInfo +// Interface to description of machine instructions +//--------------------------------------------------------------------------- + + +/*ctor*/ +MachineInstrInfo::MachineInstrInfo(const MachineInstrDescriptor* _desc, + unsigned int _descSize, + unsigned int _numRealOpCodes) + : desc(_desc), descSize(_descSize), numRealOpCodes(_numRealOpCodes) +{ + assert(TargetInstrDescriptors == NULL && desc != NULL); + TargetInstrDescriptors = desc; // initialize global variable +} + + +/*dtor*/ +MachineInstrInfo::~MachineInstrInfo() +{ + TargetInstrDescriptors = NULL; // reset global variable +} + + +bool +MachineInstrInfo::constantFitsInImmedField(MachineOpCode opCode, + int64_t intValue) const +{ + // First, check if opCode has an immed field. + bool isSignExtended; + uint64_t maxImmedValue = this->maxImmedConstant(opCode, isSignExtended); + if (maxImmedValue != 0) + { + // Now check if the constant fits + if (intValue <= (int64_t) maxImmedValue && + intValue >= -((int64_t) maxImmedValue+1)) + return true; + } + + return false; +} + + +//--------------------------------------------------------------------------- +// class MachineSchedInfo +// Interface to machine description for instruction scheduling +//--------------------------------------------------------------------------- + +/*ctor*/ +MachineSchedInfo::MachineSchedInfo(int _numSchedClasses, + const MachineInstrInfo* _mii, + const InstrClassRUsage* _classRUsages, + const InstrRUsageDelta* _usageDeltas, + const InstrIssueDelta* _issueDeltas, + unsigned int _numUsageDeltas, + unsigned int _numIssueDeltas) + : numSchedClasses(_numSchedClasses), + mii(_mii), + classRUsages(_classRUsages), + usageDeltas(_usageDeltas), + issueDeltas(_issueDeltas), + numUsageDeltas(_numUsageDeltas), + numIssueDeltas(_numIssueDeltas) +{ +} + +void +MachineSchedInfo::initializeResources() +{ + assert(MAX_NUM_SLOTS >= (int) getMaxNumIssueTotal() + && "Insufficient slots for static data! Increase MAX_NUM_SLOTS"); + + // First, compute common resource usage info for each class because + // most instructions will probably behave the same as their class. + // Cannot allocate a vector of InstrRUsage so new each one. + // + vector instrRUForClasses; + instrRUForClasses.resize(numSchedClasses); + for (InstrSchedClass sc=0; sc < numSchedClasses; sc++) + { + // instrRUForClasses.push_back(new InstrRUsage); + instrRUForClasses[sc].setMaxSlots(getMaxNumIssueTotal()); + instrRUForClasses[sc] = classRUsages[sc]; + } + + computeInstrResources(instrRUForClasses); + + computeIssueGaps(instrRUForClasses); +} + + +void +MachineSchedInfo::computeInstrResources(const vector& instrRUForClasses) +{ + int numOpCodes = mii->getNumRealOpCodes(); + instrRUsages.resize(numOpCodes); + + // First get the resource usage information from the class resource usages. + for (MachineOpCode op=0; op < numOpCodes; op++) + { + InstrSchedClass sc = getSchedClass(op); + assert(sc >= 0 && sc < numSchedClasses); + instrRUsages[op] = instrRUForClasses[sc]; + } + + // Now, modify the resource usages as specified in the deltas. + for (unsigned i=0; i < numUsageDeltas; i++) + { + MachineOpCode op = usageDeltas[i].opCode; + assert(op < numOpCodes); + instrRUsages[op].addUsageDelta(usageDeltas[i]); + } + + // Then modify the issue restrictions as specified in the deltas. + for (unsigned i=0; i < numIssueDeltas; i++) + { + MachineOpCode op = issueDeltas[i].opCode; + assert(op < numOpCodes); + instrRUsages[issueDeltas[i].opCode].addIssueDelta(issueDeltas[i]); + } +} + + +void +MachineSchedInfo::computeIssueGaps(const vector& instrRUForClasses) +{ + int numOpCodes = mii->getNumRealOpCodes(); + instrRUsages.resize(numOpCodes); + + assert(numOpCodes < (1 << MAX_OPCODE_SIZE) - 1 + && "numOpCodes invalid for implementation of class OpCodePair!"); + + // First, compute issue gaps between pairs of classes based on common + // resources usages for each class, because most instruction pairs will + // usually behave the same as their class. + // + int classPairGaps[numSchedClasses][numSchedClasses]; + for (InstrSchedClass fromSC=0; fromSC < numSchedClasses; fromSC++) + for (InstrSchedClass toSC=0; toSC < numSchedClasses; toSC++) + { + int classPairGap = ComputeMinGap(instrRUForClasses[fromSC], + instrRUForClasses[toSC]); + classPairGaps[fromSC][toSC] = classPairGap; + } + + // Now, for each pair of instructions, use the class pair gap if both + // instructions have identical resource usage as their respective classes. + // If not, recompute the gap for the pair from scratch. + + longestIssueConflict = 0; + + for (MachineOpCode fromOp=0; fromOp < numOpCodes; fromOp++) + for (MachineOpCode toOp=0; toOp < numOpCodes; toOp++) + { + int instrPairGap = + (instrRUsages[fromOp].sameAsClass && instrRUsages[toOp].sameAsClass) + ? classPairGaps[getSchedClass(fromOp)][getSchedClass(toOp)] + : ComputeMinGap(instrRUsages[fromOp], instrRUsages[toOp]); + + if (instrPairGap > 0) + { + issueGaps[OpCodePair(fromOp,toOp)] = instrPairGap; + conflictLists[fromOp].push_back(toOp); + longestIssueConflict = max(longestIssueConflict, instrPairGap); + } + } +} + + +// Check if fromRVec and toRVec have *any* common entries. +// Assume the vectors are sorted in increasing order. +// Algorithm copied from function set_intersection() for sorted ranges (stl_algo.h). +inline static bool +RUConflict(const vector& fromRVec, + const vector& toRVec) +{ + bool commonElementFound = false; + + unsigned fN = fromRVec.size(), tN = toRVec.size(); + unsigned fi = 0, ti = 0; + while (fi < fN && ti < tN) + if (fromRVec[fi] < toRVec[ti]) + ++fi; + else if (toRVec[ti] < fromRVec[fi]) + ++ti; + else + { + commonElementFound = true; + break; + } + + return commonElementFound; +} + + +static cycles_t +ComputeMinGap(const InstrRUsage& fromRU, const InstrRUsage& toRU) +{ + cycles_t minGap = 0; + + if (fromRU.numBubbles > 0) + minGap = fromRU.numBubbles; + + if (minGap < fromRU.numCycles) + { + // only need to check from cycle `minGap' onwards + for (cycles_t gap=minGap; gap <= fromRU.numCycles-1; gap++) + { + // check if instr. #2 can start executing `gap' cycles after #1 + // by checking for resource conflicts in each overlapping cycle + cycles_t numOverlap = min(fromRU.numCycles - gap, toRU.numCycles); + for (cycles_t c = 0; c <= numOverlap-1; c++) + if (RUConflict(fromRU.resourcesByCycle[gap + c], + toRU.resourcesByCycle[c])) + {// conflict found so minGap must be more than `gap' + minGap = gap+1; + break; + } + } + } + + return minGap; +} + +//--------------------------------------------------------------------------- diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index fb5c1fc9456..789087f9a5f 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -1,14 +1,13 @@ -//===------------------------------------------------------------------------=== -// LLVM 'LLC' UTILITY +//===-- llc.cpp - Implement the LLVM Compiler -----------------------------===// // // This is the llc compiler driver. // -//===------------------------------------------------------------------------=== +//===----------------------------------------------------------------------===// #include "llvm/Bytecode/Reader.h" #include "llvm/Optimizations/Normalize.h" -#include "llvm/CodeGen/Sparc.h" -#include "llvm/CodeGen/TargetMachine.h" +#include "llvm/Target/Sparc.h" +#include "llvm/Target/Machine.h" #include "llvm/Support/CommandLine.h" #include "llvm/Module.h" #include "llvm/Method.h" @@ -20,46 +19,39 @@ static void NormalizeMethod(Method* method) { NormalizePhiConstantArgs(method); } - -static bool CompileModule(Module *M, TargetMachine &Target) { - for (Module::const_iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) { - Method *Meth = *MI; - - NormalizeMethod(Meth); - - if (Target.compileMethod(Meth)) return true; - } - - return false; -} - - - -//--------------------------------------------------------------------------- +//===----------------------------------------------------------------------===// // Function main() +//===----------------------------------------------------------------------===// // // Entry point for the llc compiler. -//--------------------------------------------------------------------------- - +// int main(int argc, char** argv) { cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n"); TargetMachine *Target = allocateSparcTargetMachine(); - Module *module = ParseBytecodeFile(InputFilename); - if (module == 0) { + Module *M = ParseBytecodeFile(InputFilename); + if (M == 0) { cerr << "bytecode didn't read correctly.\n"; + delete Target; return 1; } - if (CompileModule(module, *Target)) { - cerr << "Error compiling " << InputFilename << "!\n"; - delete module; - return 1; + bool Failed = false; + for (Module::const_iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) { + Method *Meth = *MI; + + NormalizeMethod(Meth); + + if (Target->compileMethod(Meth)) { + cerr << "Error compiling " << InputFilename << "!\n"; + Failed = true; + break; + } } // Clean up and exit - delete module; + delete M; delete Target; - return 0; + return Failed; }