2 //***************************************************************************
9 // 7/12/01 - Vikram Adve - Created
10 //**************************************************************************/
12 #ifndef LLVM_CODEGEN_TARGETMACHINE_H
13 #define LLVM_CODEGEN_TARGETMACHINE_H
15 //*********************** System Include Files *****************************/
23 //************************ User Include Files *****************************/
25 #include "llvm/CodeGen/TargetData.h"
26 #include "llvm/Support/NonCopyable.h"
27 #include "llvm/Support/DataTypes.h"
29 //************************ Opaque Declarations*****************************/
33 struct MachineInstrDescriptor;
36 //************************ Exported Data Types *****************************/
38 //---------------------------------------------------------------------------
39 // Data types used to define information about a single machine instruction
40 //---------------------------------------------------------------------------
42 typedef int MachineOpCode;
43 typedef int OpCodeMask;
44 typedef int InstrSchedClass;
46 static const unsigned MAX_OPCODE_SIZE = 16;
48 typedef long long cycles_t;
49 const cycles_t HUGE_LATENCY = ~((unsigned long long) 1 << sizeof(cycles_t)-1);
50 const cycles_t INVALID_LATENCY = -HUGE_LATENCY;
55 long val; // make long by concatenating two opcodes
56 OpCodePair(MachineOpCode op1, MachineOpCode op2)
57 : val((op1 < 0 || op2 < 0)?
58 -1 : (long)((((unsigned) op1) << MAX_OPCODE_SIZE) | (unsigned) op2)) {}
59 bool operator==(const OpCodePair& op) const {
63 OpCodePair(); // disable for now
67 template <> struct hash<OpCodePair> {
68 size_t operator()(const OpCodePair& pair) const {
69 return hash<long>()(pair.val);
74 // Global variable holding an array of descriptors for machine instructions.
75 // The actual object needs to be created separately for each target machine.
76 // This variable is initialized and reset by class MachineInstrInfo.
78 extern const MachineInstrDescriptor* TargetInstrDescriptors;
81 //---------------------------------------------------------------------------
82 // struct MachineInstrDescriptor:
83 // Predefined information about each machine instruction.
84 // Designed to initialized statically.
86 // class MachineInstructionInfo
87 // Interface to description of machine instructions
89 //---------------------------------------------------------------------------
92 const unsigned int M_NOP_FLAG = 1;
93 const unsigned int M_BRANCH_FLAG = 1 << 1;
94 const unsigned int M_CALL_FLAG = 1 << 2;
95 const unsigned int M_RET_FLAG = 1 << 3;
96 const unsigned int M_ARITH_FLAG = 1 << 4;
97 const unsigned int M_CC_FLAG = 1 << 6;
98 const unsigned int M_LOGICAL_FLAG = 1 << 6;
99 const unsigned int M_INT_FLAG = 1 << 7;
100 const unsigned int M_FLOAT_FLAG = 1 << 8;
101 const unsigned int M_CONDL_FLAG = 1 << 9;
102 const unsigned int M_LOAD_FLAG = 1 << 10;
103 const unsigned int M_PREFETCH_FLAG = 1 << 11;
104 const unsigned int M_STORE_FLAG = 1 << 12;
105 const unsigned int M_DUMMY_PHI_FLAG = 1 << 13;
108 struct MachineInstrDescriptor {
109 string opCodeString; // Assembly language mnemonic for the opcode.
110 int numOperands; // Number of args; -1 if variable #args
111 int resultPos; // Position of the result; -1 if no result
112 unsigned int maxImmedConst; // Largest +ve constant in IMMMED field or 0.
113 bool immedIsSignExtended; // Is IMMED field sign-extended? If so,
114 // smallest -ve value is -(maxImmedConst+1).
115 unsigned int numDelaySlots; // Number of delay slots after instruction
116 unsigned int latency; // Latency in machine cycles
117 InstrSchedClass schedClass; // enum identifying instr sched class
118 unsigned int iclass; // flags identifying machine instr class
122 class MachineInstrInfo : public NonCopyableV {
124 const MachineInstrDescriptor* desc; // raw array to allow static init'n
125 unsigned int descSize; // number of entries in the desc array
126 unsigned int numRealOpCodes; // number of non-dummy op codes
129 /*ctor*/ MachineInstrInfo(const MachineInstrDescriptor* _desc,
130 unsigned int _descSize,
131 unsigned int _numRealOpCodes);
132 /*dtor*/ virtual ~MachineInstrInfo();
134 unsigned int getNumRealOpCodes() const {
135 return numRealOpCodes;
138 unsigned int getNumTotalOpCodes() const {
142 const MachineInstrDescriptor& getDescriptor(MachineOpCode opCode) const {
143 assert(opCode >= 0 && opCode < (int) descSize);
147 int getNumOperands (MachineOpCode opCode) const {
148 return getDescriptor(opCode).numOperands;
151 int getResultPos (MachineOpCode opCode) const {
152 return getDescriptor(opCode).resultPos;
155 unsigned int getNumDelaySlots(MachineOpCode opCode) const {
156 return getDescriptor(opCode).numDelaySlots;
159 InstrSchedClass getSchedClass (MachineOpCode opCode) const {
160 return getDescriptor(opCode).schedClass;
164 // Query instruction class flags according to the machine-independent
165 // flags listed above.
167 unsigned int getIClass (MachineOpCode opCode) const {
168 return getDescriptor(opCode).iclass;
170 bool isNop (MachineOpCode opCode) const {
171 return getDescriptor(opCode).iclass & M_NOP_FLAG;
173 bool isBranch (MachineOpCode opCode) const {
174 return getDescriptor(opCode).iclass & M_BRANCH_FLAG;
176 bool isCall (MachineOpCode opCode) const {
177 return getDescriptor(opCode).iclass & M_CALL_FLAG;
179 bool isReturn (MachineOpCode opCode) const {
180 return getDescriptor(opCode).iclass & M_RET_FLAG;
182 bool isControlFlow (MachineOpCode opCode) const {
183 return getDescriptor(opCode).iclass & M_BRANCH_FLAG
184 || getDescriptor(opCode).iclass & M_CALL_FLAG
185 || getDescriptor(opCode).iclass & M_RET_FLAG;
187 bool isArith (MachineOpCode opCode) const {
188 return getDescriptor(opCode).iclass & M_RET_FLAG;
190 bool isCCInstr (MachineOpCode opCode) const {
191 return getDescriptor(opCode).iclass & M_CC_FLAG;
193 bool isLogical (MachineOpCode opCode) const {
194 return getDescriptor(opCode).iclass & M_LOGICAL_FLAG;
196 bool isIntInstr (MachineOpCode opCode) const {
197 return getDescriptor(opCode).iclass & M_INT_FLAG;
199 bool isFloatInstr (MachineOpCode opCode) const {
200 return getDescriptor(opCode).iclass & M_FLOAT_FLAG;
202 bool isConditional (MachineOpCode opCode) const {
203 return getDescriptor(opCode).iclass & M_CONDL_FLAG;
205 bool isLoad (MachineOpCode opCode) const {
206 return getDescriptor(opCode).iclass & M_LOAD_FLAG;
208 bool isPrefetch (MachineOpCode opCode) const {
209 return getDescriptor(opCode).iclass & M_PREFETCH_FLAG;
211 bool isLoadOrPrefetch (MachineOpCode opCode) const {
212 return getDescriptor(opCode).iclass & M_LOAD_FLAG
213 || getDescriptor(opCode).iclass & M_PREFETCH_FLAG;
215 bool isStore (MachineOpCode opCode) const {
216 return getDescriptor(opCode).iclass & M_STORE_FLAG;
218 bool isMemoryAccess (MachineOpCode opCode) const {
219 return getDescriptor(opCode).iclass & M_LOAD_FLAG
220 || getDescriptor(opCode).iclass & M_PREFETCH_FLAG
221 || getDescriptor(opCode).iclass & M_STORE_FLAG;
223 bool isDummyPhiInstr (MachineOpCode opCode) const {
224 return getDescriptor(opCode).iclass & M_DUMMY_PHI_FLAG;
228 // Check if an instruction can be issued before its operands are ready,
229 // or if a subsequent instruction that uses its result can be issued
230 // before the results are ready.
231 // Default to true since most instructions on many architectures allow this.
233 virtual bool hasOperandInterlock(MachineOpCode opCode) const {
237 virtual bool hasResultInterlock(MachineOpCode opCode) const {
242 // Latencies for individual instructions and instruction pairs
244 virtual int minLatency (MachineOpCode opCode) const {
245 return getDescriptor(opCode).latency;
248 virtual int maxLatency (MachineOpCode opCode) const {
249 return getDescriptor(opCode).latency;
252 // Check if the specified constant fits in the immediate field
253 // of this machine instruction
255 virtual bool constantFitsInImmedField(MachineOpCode opCode,
256 int64_t intValue) const;
258 // Return the largest +ve constant that can be held in the IMMMED field
259 // of this machine instruction.
260 // isSignExtended is set to true if the value is sign-extended before use
261 // (this is true for all immediate fields in SPARC instructions).
262 // Return 0 if the instruction has no IMMED field.
264 virtual uint64_t maxImmedConstant(MachineOpCode opCode,
265 bool& isSignExtended) const {
266 isSignExtended = getDescriptor(opCode).immedIsSignExtended;
267 return getDescriptor(opCode).maxImmedConst;
272 //---------------------------------------------------------------------------
273 // class MachineResource
277 // Representation of a single machine resource used in specifying
278 // resource usages of machine instructions for scheduling.
279 //---------------------------------------------------------------------------
282 typedef unsigned int resourceId_t;
284 class MachineResource {
289 /*ctor*/ MachineResource(const string& resourceName)
290 : rname(resourceName), rid(nextId++) {}
293 static resourceId_t nextId;
294 MachineResource(); // disable
298 class CPUResource : public MachineResource {
300 int maxNumUsers; // MAXINT if no restriction
302 /*ctor*/ CPUResource(const string& rname, int maxUsers)
303 : MachineResource(rname), maxNumUsers(maxUsers) {}
307 //---------------------------------------------------------------------------
308 // struct InstrClassRUsage
309 // struct InstrRUsageDelta
310 // struct InstrIssueDelta
311 // struct InstrRUsage
314 // The first three are structures used to specify machine resource
315 // usages for each instruction in a machine description file:
316 // InstrClassRUsage : resource usages common to all instrs. in a class
317 // InstrRUsageDelta : add/delete resource usage for individual instrs.
318 // InstrIssueDelta : add/delete instr. issue info for individual instrs
320 // The last one (InstrRUsage) is the internal representation of
321 // instruction resource usage constructed from the above three.
322 //---------------------------------------------------------------------------
324 const int MAX_NUM_SLOTS = 32;
325 const int MAX_NUM_CYCLES = 32;
327 struct InstrClassRUsage {
328 InstrSchedClass schedClass;
331 // Issue restrictions common to instructions in this class
332 unsigned int maxNumIssue;
337 // Feasible slots to use for instructions in this class.
338 // The size of vector S[] is `numSlots'.
339 unsigned int numSlots;
340 unsigned int feasibleSlots[MAX_NUM_SLOTS];
342 // Resource usages common to instructions in this class.
343 // The size of vector V[] is `numRUEntries'.
344 unsigned int numRUEntries;
346 resourceId_t resourceId;
347 unsigned int startCycle;
352 struct InstrRUsageDelta {
353 MachineOpCode opCode;
354 resourceId_t resourceId;
355 unsigned int startCycle;
359 // Specify instruction issue restrictions for individual instructions
360 // that differ from the common rules for the class.
362 struct InstrIssueDelta {
363 MachineOpCode opCode;
371 /*ctor*/ InstrRUsage () {}
372 /*ctor*/ InstrRUsage (const InstrRUsage& instrRU);
373 InstrRUsage& operator= (const InstrRUsage& instrRU);
377 // Issue restrictions for this instruction
382 // Feasible slots to use for this instruction.
383 vector<bool> feasibleSlots;
385 // Resource usages for this instruction, with one resource vector per cycle.
387 vector<vector<resourceId_t> > resourcesByCycle;
390 // Conveniences for initializing this structure
391 InstrRUsage& operator= (const InstrClassRUsage& classRU);
392 void addIssueDelta (const InstrIssueDelta& delta);
393 void addUsageDelta (const InstrRUsageDelta& delta);
394 void setMaxSlots (int maxNumSlots);
396 friend class MachineSchedInfo; // give access to these functions
401 InstrRUsage::setMaxSlots(int maxNumSlots)
403 feasibleSlots.resize(maxNumSlots);
407 InstrRUsage::operator=(const InstrRUsage& instrRU)
409 sameAsClass = instrRU.sameAsClass;
410 isSingleIssue = instrRU.isSingleIssue;
411 breaksGroup = instrRU.breaksGroup;
412 numBubbles = instrRU.numBubbles;
413 feasibleSlots = instrRU.feasibleSlots;
414 numCycles = instrRU.numCycles;
415 resourcesByCycle = instrRU.resourcesByCycle;
420 InstrRUsage::InstrRUsage(const InstrRUsage& instrRU)
426 InstrRUsage::operator=(const InstrClassRUsage& classRU)
429 isSingleIssue = classRU.isSingleIssue;
430 breaksGroup = classRU.breaksGroup;
431 numBubbles = classRU.numBubbles;
433 for (unsigned i=0; i < classRU.numSlots; i++)
435 unsigned slot = classRU.feasibleSlots[i];
436 assert(slot < feasibleSlots.size() && "Invalid slot specified!");
437 this->feasibleSlots[slot] = true;
440 this->numCycles = classRU.totCycles;
441 this->resourcesByCycle.resize(this->numCycles);
443 for (unsigned i=0; i < classRU.numRUEntries; i++)
444 for (unsigned c=classRU.V[i].startCycle, NC = c + classRU.V[i].numCycles;
446 this->resourcesByCycle[c].push_back(classRU.V[i].resourceId);
448 // Sort each resource usage vector by resourceId_t to speed up conflict checking
449 for (unsigned i=0; i < this->resourcesByCycle.size(); i++)
450 sort(resourcesByCycle[i].begin(), resourcesByCycle[i].end());
457 InstrRUsage::addIssueDelta(const InstrIssueDelta& delta)
460 isSingleIssue = delta.isSingleIssue;
461 breaksGroup = delta.breaksGroup;
462 numBubbles = delta.numBubbles;
466 // Add the extra resource usage requirements specified in the delta.
467 // Note that a negative value of `numCycles' means one entry for that
468 // resource should be deleted for each cycle.
471 InstrRUsage::addUsageDelta(const InstrRUsageDelta& delta)
473 int NC = delta.numCycles;
475 this->sameAsClass = false;
477 // resize the resources vector if more cycles are specified
478 unsigned maxCycles = this->numCycles;
479 maxCycles = max(maxCycles, delta.startCycle + abs(NC) - 1);
480 if (maxCycles > this->numCycles)
482 this->resourcesByCycle.resize(maxCycles);
483 this->numCycles = maxCycles;
487 for (unsigned c=delta.startCycle, last=c+NC-1; c <= last; c++)
488 this->resourcesByCycle[c].push_back(delta.resourceId);
490 // Remove the resource from all NC cycles.
491 for (unsigned c=delta.startCycle, last=(c-NC)-1; c <= last; c++)
493 // Look for the resource backwards so we remove the last entry
494 // for that resource in each cycle.
495 vector<resourceId_t>& rvec = this->resourcesByCycle[c];
497 for (r = (int) rvec.size(); r >= 0; r--)
498 if (rvec[r] == delta.resourceId)
499 {// found last entry for the resource
500 rvec.erase(rvec.begin() + r);
503 assert(r >= 0 && "Resource to remove was unused in cycle c!");
508 //---------------------------------------------------------------------------
509 // class MachineSchedInfo
512 // Common interface to machine information for instruction scheduling
513 //---------------------------------------------------------------------------
515 class MachineSchedInfo : public NonCopyableV {
517 unsigned int maxNumIssueTotal;
518 int longestIssueConflict;
520 int branchMispredictPenalty; // 4 for SPARC IIi
521 int branchTargetUnknownPenalty; // 2 for SPARC IIi
522 int l1DCacheMissPenalty; // 7 or 9 for SPARC IIi
523 int l1ICacheMissPenalty; // ? for SPARC IIi
525 bool inOrderLoads ; // true for SPARC IIi
526 bool inOrderIssue; // true for SPARC IIi
527 bool inOrderExec; // false for most architectures
528 bool inOrderRetire; // true for most architectures
531 inline const InstrRUsage& getInstrRUsage(MachineOpCode opCode) const {
532 assert(opCode >= 0 && opCode < (int) instrRUsages.size());
533 return instrRUsages[opCode];
535 inline const InstrClassRUsage&
536 getClassRUsage(const InstrSchedClass& sc) const {
537 assert(sc >= 0 && sc < numSchedClasses);
538 return classRUsages[sc];
542 /*ctor*/ MachineSchedInfo (int _numSchedClasses,
543 const MachineInstrInfo* _mii,
544 const InstrClassRUsage* _classRUsages,
545 const InstrRUsageDelta* _usageDeltas,
546 const InstrIssueDelta* _issueDeltas,
547 unsigned int _numUsageDeltas,
548 unsigned int _numIssueDeltas);
549 /*dtor*/ virtual ~MachineSchedInfo () {}
551 inline const MachineInstrInfo& getInstrInfo() const {
555 inline int getNumSchedClasses() const {
556 return numSchedClasses;
559 inline unsigned int getMaxNumIssueTotal() const {
560 return maxNumIssueTotal;
563 inline unsigned int getMaxIssueForClass(const InstrSchedClass& sc) const {
564 assert(sc >= 0 && sc < numSchedClasses);
565 return classRUsages[sc].maxNumIssue;
568 inline InstrSchedClass getSchedClass (MachineOpCode opCode) const {
569 return getInstrInfo().getSchedClass(opCode);
572 inline bool instrCanUseSlot (MachineOpCode opCode,
574 assert(s < getInstrRUsage(opCode).feasibleSlots.size() && "Invalid slot!");
575 return getInstrRUsage(opCode).feasibleSlots[s];
578 inline int getLongestIssueConflict () const {
579 return longestIssueConflict;
582 inline int getMinIssueGap (MachineOpCode fromOp,
583 MachineOpCode toOp) const {
584 hash_map<OpCodePair,int>::const_iterator
585 I = issueGaps.find(OpCodePair(fromOp, toOp));
586 return (I == issueGaps.end())? 0 : (*I).second;
589 inline const vector<MachineOpCode>*
590 getConflictList(MachineOpCode opCode) const {
591 hash_map<MachineOpCode,vector<MachineOpCode> >::const_iterator
592 I = conflictLists.find(opCode);
593 return (I == conflictLists.end())? NULL : & (*I).second;
596 inline bool isSingleIssue (MachineOpCode opCode) const {
597 return getInstrRUsage(opCode).isSingleIssue;
600 inline bool breaksIssueGroup (MachineOpCode opCode) const {
601 return getInstrRUsage(opCode).breaksGroup;
604 inline unsigned int numBubblesAfter (MachineOpCode opCode) const {
605 return getInstrRUsage(opCode).numBubbles;
609 virtual void initializeResources ();
612 void computeInstrResources(const vector<InstrRUsage>& instrRUForClasses);
613 void computeIssueGaps(const vector<InstrRUsage>& instrRUForClasses);
617 const MachineInstrInfo* mii;
618 const InstrClassRUsage* classRUsages; // raw array by sclass
619 const InstrRUsageDelta* usageDeltas; // raw array [1:numUsageDeltas]
620 const InstrIssueDelta* issueDeltas; // raw array [1:numIssueDeltas]
621 unsigned int numUsageDeltas;
622 unsigned int numIssueDeltas;
624 vector<InstrRUsage> instrRUsages; // indexed by opcode
625 hash_map<OpCodePair,int> issueGaps; // indexed by opcode pair
626 hash_map<MachineOpCode,vector<MachineOpCode> >
627 conflictLists; // indexed by opcode
631 //---------------------------------------------------------------------------
632 // class TargetMachine
635 // Primary interface to machine description for the target machine.
637 //---------------------------------------------------------------------------
639 class TargetMachine : public NonCopyableV {
641 const string TargetName;
642 const TargetData DataLayout; // Calculates type size & alignment
643 int optSizeForSubWordData;
644 int minMemOpWordSize;
645 int maxAtomicMemOpWordSize;
647 // Register information. This needs to be reorganized into a single class.
648 int zeroRegNum; // register that gives 0 if any (-1 if none)
651 /*ctor*/ TargetMachine(const string &targetname,
652 unsigned char PtrSize = 8, unsigned char PtrAl = 8,
653 unsigned char DoubleAl = 8, unsigned char FloatAl = 4,
654 unsigned char LongAl = 8, unsigned char IntAl = 4,
655 unsigned char ShortAl = 2, unsigned char ByteAl = 1)
656 : TargetName(targetname), DataLayout(targetname, PtrSize, PtrAl,
657 DoubleAl, FloatAl, LongAl, IntAl,
661 /*dtor*/ virtual ~TargetMachine() {}
663 const MachineInstrInfo& getInstrInfo () const { return *machineInstrInfo; }
665 const MachineSchedInfo& getSchedInfo() const { return *machineSchedInfo; }
667 virtual unsigned int findOptimalStorageSize (const Type* ty) const;
669 // This really should be in the register info class
670 virtual bool regsMayBeAliased (unsigned int regNum1,
671 unsigned int regNum2) const {
672 return (regNum1 == regNum2);
676 // Description of machine instructions
677 // Protect so that subclass can control alloc/dealloc
678 MachineInstrInfo* machineInstrInfo;
679 MachineSchedInfo* machineSchedInfo;
682 //**************************************************************************/