diff --git a/llvm/include/llvm/CodeGen/InstrForest.h b/llvm/include/llvm/CodeGen/InstrForest.h new file mode 100644 index 000000000000..c49933f3b34a --- /dev/null +++ b/llvm/include/llvm/CodeGen/InstrForest.h @@ -0,0 +1,339 @@ +/* $Id$ -*-c++-*- + **************************************************************************** + * File: + * InstrForest.h + * + * Purpose: + * Convert SSA graph to instruction trees for instruction selection. + * + * Strategy: + * The basic idea is that we would like to group instructions into a single + * tree if one or more of them might be potentially combined into a single + * complex instruction in the target machine. + * Since this grouping is completely machine-independent, it is as + * aggressive as possible. In particular, we group two instructions + * O and I if: + * (1) Instruction O computes an operand of instruction I, and + * (2) O and I are part of the same basic block, and + * (3) O has only a single use, viz., I. + * + * History: + * 6/28/01 - Vikram Adve - Created + ***************************************************************************/ + +#ifndef LLVM_CODEGEN_INSTRFOREST_H +#define LLVM_CODEGEN_INSTRFOREST_H + +/* + CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC + C + C The following types and macros are visible to the C code generated + C by BURG. + */ + +extern "C" { + + //------------------------------------------------------------------------- + // Data types needed by BURG and implemented by us + //------------------------------------------------------------------------- + + typedef int OpLabel; + typedef int StateLabel; + + typedef struct BasicTreeNode_struct { + + BasicTreeNode_struct* leftChild; + BasicTreeNode_struct* rightChild; + BasicTreeNode_struct* parent; + OpLabel opLabel; + StateLabel state; + void* treeNodePtr; /* points to the C++ tree node object + * that "contains" this node */ + } BasicTreeNode; + + //------------------------------------------------------------------------- + // Declarations of data and functions created by BURG + //------------------------------------------------------------------------- + +# ifdef __STDC__ +# define ARGS(x) x +# else +# define ARGS(x) () +# endif + + extern short* burm_nts[]; + + extern StateLabel burm_label ARGS((BasicTreeNode* p)); + + extern StateLabel burm_state ARGS((OpLabel op, + StateLabel leftState, + StateLabel rightState)); + + extern StateLabel burm_rule ARGS((StateLabel state, + int goalNT)); + + extern BasicTreeNode** burm_kids ARGS((BasicTreeNode* p, + int eruleno, + BasicTreeNode* kids[])); + + extern void printcover ARGS((BasicTreeNode*, int, int)); + extern void printtree ARGS((BasicTreeNode*)); + extern int treecost ARGS((BasicTreeNode*, int, int)); + extern void printMatches ARGS((BasicTreeNode*)); + +} +/* end extern "C" */ + + +/*CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC*/ + + +#ifdef __cplusplus + +//************************** System Include Files **************************/ + +#include +#include +#include + +//*************************** User Include Files ***************************/ + +#include "llvm/Support/Unique.h" +#include "llvm/Instruction.h" + +//************************* Opaque Declarations ****************************/ + +class Value; +class Instruction; +class ConstPoolVal; +class BasicBlock; +class Method; +class InstrTreeNode; +class InstrForest; + +//************************ Exported Constants ******************************/ + + +//-------------------------------------------------------------------------- +// OpLabel values for special-case nodes created for instruction selection. +// All op-labels not defined here are identical to the instruction +// opcode returned by Instruction::getInstType() +//-------------------------------------------------------------------------- + +const int InvalidOp = -1; +const int VRegListOp = 97; +const int VRegNodeOp = 98; +const int ConstantNodeOp= 99; +const int LabelNodeOp = 100; + +const int RetValueOp = 100 + Instruction::Ret; +const int BrCondOp = 100 + Instruction::Br; + +const int SetCCOp = 100 + Instruction::SetEQ; + +const int AllocaN = 100 + Instruction::Alloca; // 121 +const int LoadIdx = 100 + Instruction::Load; // 122 +const int GetElemPtrIdx= 100 + Instruction::GetElementPtr; // 124 + +const int ToBoolTy = 100 + Instruction::Cast; // 126 +const int ToUByteTy = ToBoolTy + 1; +const int ToSByteTy = ToBoolTy + 2; +const int ToUShortTy = ToBoolTy + 3; +const int ToShortTy = ToBoolTy + 4; +const int ToUIntTy = ToBoolTy + 5; +const int ToIntTy = ToBoolTy + 6; +const int ToULongTy = ToBoolTy + 7; +const int ToLongTy = ToBoolTy + 8; +const int ToFloatTy = ToBoolTy + 9; +const int ToDoubleTy = ToBoolTy + 10; +const int ToArrayTy = ToBoolTy + 11; +const int ToPointerTy = ToBoolTy + 12; + + +//************************ Exported Data Types *****************************/ + +struct ptrHashFunc { + inline size_t operator()(const void* const& p) const + { + // Copied from body of hash::operator(). + // I cannot figure out how to invoke that without an object + return (size_t) ((const unsigned long) p); + } +}; + + +//------------------------------------------------------------------------ +// class InstrTreeNode +// +// A single tree node in the instruction tree used for +// instruction selection via BURG. +//------------------------------------------------------------------------ + +inline InstrTreeNode* +MainTreeNode(BasicTreeNode* node) { + return (InstrTreeNode*) node->treeNodePtr; +} + + +class InstrTreeNode: public Unique { +public: + enum InstrTreeNodeType { NTInstructionNode, + NTVRegListNode, + NTVRegNode, + NTConstNode, + NTLabelNode }; + +protected: + BasicTreeNode basicNode; + InstrTreeNodeType treeNodeType; + Value* val; + +public: + /*ctor*/ InstrTreeNode (InstrTreeNodeType nodeType, + Value* _val); + /*dtor*/ virtual ~InstrTreeNode (); + + BasicTreeNode* getBasicNode () { return &basicNode; } + + InstrTreeNodeType getNodeType () const { return treeNodeType; } + + Value* getValue () const { return val; } + + inline OpLabel getOpLabel () const { return basicNode.opLabel; } + + inline InstrTreeNode* leftChild () const { + return (InstrTreeNode*) + (basicNode.leftChild? basicNode.leftChild->treeNodePtr : NULL); + } + + // If right child is a list node, recursively get its *left* child + inline InstrTreeNode* rightChild () const { + return (InstrTreeNode*) + (basicNode.rightChild + ? (MainTreeNode(basicNode.rightChild)->getOpLabel() == VRegListOp + ? MainTreeNode(basicNode.rightChild)->leftChild() + : MainTreeNode(basicNode.rightChild)) + : NULL); + } + + inline InstrTreeNode* parent () const { + return (InstrTreeNode*) + (basicNode.parent? basicNode.parent->treeNodePtr : NULL); + } + + void dump (int dumpChildren, + int indent) const; + +protected: + virtual void dumpNode (int indent) const = 0; + + friend class InstrForest; +}; + + +class InstructionNode: public InstrTreeNode { +public: + /*ctor*/ InstructionNode (Instruction* _instr); + Instruction* getInstruction () const { return (Instruction*) val; } + void reverseBinaryArgumentOrder(); +protected: + virtual void dumpNode (int indent) const; +}; + + +class VRegListNode: public InstrTreeNode { +public: + /*ctor*/ VRegListNode (); +protected: + virtual void dumpNode (int indent) const; +}; + + +class VRegNode: public InstrTreeNode { +public: + /*ctor*/ VRegNode (Value* _val); +protected: + virtual void dumpNode (int indent) const; +}; + + +class ConstantNode: public InstrTreeNode { +public: + /*ctor*/ ConstantNode (ConstPoolVal* constVal); + ConstPoolVal* getConstVal () const { return (ConstPoolVal*) val;} +protected: + virtual void dumpNode ( int indent) const; +}; + + +class LabelNode: public InstrTreeNode { +public: + /*ctor*/ LabelNode (BasicBlock* _bblock); + BasicBlock* getBasicBlock () const { return (BasicBlock*) val;} +protected: + virtual void dumpNode (int indent) const; +}; + + +//------------------------------------------------------------------------ +// class InstrForest +// +// A forest of instruction trees, usually for a single method. +// +// Methods: +// buildTreesForMethod() Builds the forest of trees for a method +// getTreeNodeForInstr() Returns the tree node for an Instruction +// getRootSet() Returns a set of root nodes for all the trees +// +//------------------------------------------------------------------------ + +class InstrForest : + public Unique, + private hash_map { + +private: + hash_set treeRoots; + +public: + /*ctor*/ InstrForest () {} + /*dtor*/ ~InstrForest () {} + + void buildTreesForMethod (Method *method); + + inline InstructionNode* + getTreeNodeForInstr(Instruction* instr) + { + return (*this)[instr]; + } + + inline const hash_set& + getRootSet() const { + return treeRoots; + } + + void dump () const; + +private: + // + // Private methods for buidling the instruction forest + // + void setLeftChild (InstrTreeNode* parent, + InstrTreeNode* child); + + void setRightChild (InstrTreeNode* parent, + InstrTreeNode* child); + + void setParent (InstrTreeNode* child, + InstrTreeNode* parent); + + void noteTreeNodeForInstr (Instruction* instr, + InstructionNode* treeNode); + + InstructionNode* buildTreeForInstruction(Instruction* instr); +}; + +//--------------------------------------------------------------------------- + +#endif /* #ifdef __cplusplus */ + +#endif /* #ifndef INSTRFOREST_H */ diff --git a/llvm/include/llvm/CodeGen/InstrSelection.h b/llvm/include/llvm/CodeGen/InstrSelection.h new file mode 100644 index 000000000000..7538a1532b2a --- /dev/null +++ b/llvm/include/llvm/CodeGen/InstrSelection.h @@ -0,0 +1,121 @@ +// $Id$ -*-c++-*- +//*************************************************************************** +// File: +// InstrSelection.h +// +// Purpose: +// +// History: +// 7/02/01 - Vikram Adve - Created +//*************************************************************************** + +#ifndef LLVM_CODEGEN_INSTR_SELECTION_H +#define LLVM_CODEGEN_INSTR_SELECTION_H + +//************************** System Include Files **************************/ + +//*************************** User Include Files ***************************/ + +#include "llvm/Instruction.h" + +//************************* Opaque Declarations ****************************/ + +class CompileContext; +class Instruction; +class Method; +class InstrForest; +class MachineInstruction; +class TmpInstruction; + + +//************************ Exported Constants ******************************/ + +const int DEBUG_INSTR_TREES = 2; +const int DEBUG_BURG_TREES = 5; + + +//****************** External Function Prototypes **************************/ + +//--------------------------------------------------------------------------- +// GLOBAL data and an external function that must be implemented +// for each architecture. +//--------------------------------------------------------------------------- + +const unsigned MAX_INSTR_PER_VMINSTR = 8; + +extern unsigned GetInstructionsByRule (InstructionNode* subtreeRoot, + int ruleForNode, + short* nts, + CompileContext& ccontext, + MachineInstr** minstrVec); + +extern bool ThisIsAChainRule (int eruleno); + + +//************************ Exported Data Types *****************************/ + + +//--------------------------------------------------------------------------- +// Function: SelectInstructionsForMethod +// +// Purpose: +// Entry point for instruction selection using BURG. +// Returns true if instruction selection failed, false otherwise. +// Implemented in machine-specific instruction selection file. +//--------------------------------------------------------------------------- + +bool SelectInstructionsForMethod (Method* method, + CompileContext& ccontext); + + +// Debugging function to print the generated instructions +void PrintMachineInstructions (Method* method, + CompileContext& ccontext); + + +//--------------------------------------------------------------------------- +// Function: FoldGetElemChain +// +// Purpose: +// Fold a chain of GetElementPtr instructions into an equivalent +// (Pointer, IndexVector) pair. Returns the pointer Value, and +// stores the resulting IndexVector in argument chainIdxVec. +//--------------------------------------------------------------------------- + +Value* FoldGetElemChain (const InstructionNode* getElemInstrNode, + vector& chainIdxVec); + + +//--------------------------------------------------------------------------- +// class TmpInstruction +// +// This class represents temporary intermediate values +// used within the machine code for a VM instruction +//--------------------------------------------------------------------------- + +class TmpInstruction : public Instruction { + TmpInstruction (const TmpInstruction &CI) : Instruction(CI.getType(), CI.getOpcode()) { + Operands.reserve(2); + Operands.push_back(Use(Operands[0], this)); + Operands.push_back(Use(Operands[1], this)); + } +public: + TmpInstruction(OtherOps Opcode, Value *S1, Value* S2, const string &Name = "") + : Instruction(S1->getType(), Opcode, Name) + { + assert(Opcode == UserOp1 && "Tmp instruction opcode invalid!"); + Operands.reserve(S2? 2 : 1); + Operands.push_back(Use(S1, this)); + if (S2) + Operands.push_back(Use(S2, this)); + } + + virtual Instruction *clone() const { return new TmpInstruction(*this); } + virtual const char *getOpcodeName() const { + return "userOp1"; + } +}; + +//**************************************************************************/ + +#endif diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h new file mode 100644 index 000000000000..0421d8ca1a7e --- /dev/null +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -0,0 +1,370 @@ +// $Id$ -*-c++-*- +//*************************************************************************** +// File: +// MachineInstr.h +// +// Purpose: +// +// +// Strategy: +// +// History: +// 7/2/01 - Vikram Adve - Created +//**************************************************************************/ + +#ifndef LLVM_CODEGEN_MACHINEINSTR_H +#define LLVM_CODEGEN_MACHINEINSTR_H + +//************************** System Include Files **************************/ + +#include +#include + +//*************************** User Include Files ***************************/ + +#include "llvm/Tools/DataTypes.h" +#include "llvm/Instruction.h" +#include "llvm/Support/Unique.h" +#include "llvm/Codegen/TargetMachine.h" + + +//************************* Opaque Declarations ****************************/ + +class Value; +class InstrTreeNode; +class InstructionNode; +class MachineInstr; +class MachineInstrInfo; +class MachineOperand; + + +//************************ Exported Data Types *****************************/ + +//--------------------------------------------------------------------------- +// class MachineOperand +// +// Purpose: +// Representation of each machine instruction operand. +// This class is designed so that you can allocate a vector of operands +// first and initialize each one later. +// +// E.g, for this VM instruction: +// ptr = alloca type, numElements +// we generate 2 machine instructions on the SPARC: +// +// mul Constant, Numelements -> Reg +// add %sp, Reg -> Ptr +// +// Each instruction has 3 operands, listed above. Of those: +// - Reg, NumElements, and Ptr are of operand type MO_Register. +// - Constant is of operand type MO_SignExtendedImmed on the SPARC. +// +// For the register operands, the virtual register type is as follows: +// +// - Reg will be of virtual register type MO_MInstrVirtualReg. The field +// MachineInstr* minstr will point to the instruction that computes reg. +// +// - %sp will be of virtual register type MO_MachineReg. +// The field regNum identifies the machine register. +// +// - NumElements will be of virtual register type MO_VirtualReg. +// The field Value* value identifies the value. +// +// - Ptr will also be of virtual register type MO_VirtualReg. +// Again, the field Value* value identifies the value. +// +//--------------------------------------------------------------------------- + +class MachineOperand { +public: + friend ostream& operator<<(ostream& os, const MachineOperand& mop); + +public: + enum MachineOperandType { + MO_Register, + MO_CCRegister, + MO_SignExtendedImmed, + MO_UnextendedImmed, + MO_PCRelativeDisp, + }; + + enum VirtualRegisterType { + MO_VirtualReg, // virtual register for *value + MO_MachineReg // pre-assigned machine register `regNum' + }; + + MachineOperandType machineOperandType; + + VirtualRegisterType vregType; + + Value* value; // BasicBlockVal for a label operand. + // ConstantVal for a non-address immediate. + // Virtual register for a register operand. + + unsigned int regNum; // register number for an explicit register + + int64_t immedVal; // constant value for an explicit constant + + /*ctor*/ MachineOperand (); + /*ctor*/ MachineOperand (MachineOperandType operandType, + Value* _val); + /*copy ctor*/ MachineOperand (const MachineOperand&); + /*dtor*/ ~MachineOperand () {} + + // These functions are provided so that a vector of operands can be + // statically allocated and individual ones can be initialized later. + // + void Initialize (MachineOperandType operandType, + Value* _val); + void InitializeConst (MachineOperandType operandType, + int64_t intValue); + void InitializeReg (unsigned int regNum); +}; + + +inline +MachineOperand::MachineOperand() + : machineOperandType(MO_Register), + vregType(MO_VirtualReg), + value(NULL), + regNum(0), + immedVal(0) +{} + +inline +MachineOperand::MachineOperand(MachineOperandType operandType, + Value* _val) + : machineOperandType(operandType), + vregType(MO_VirtualReg), + value(_val), + regNum(0), + immedVal(0) +{} + +inline +MachineOperand::MachineOperand(const MachineOperand& mo) + : machineOperandType(mo.machineOperandType), + vregType(mo.vregType), + value(mo.value), + regNum(mo.regNum), + immedVal(mo.immedVal) +{ +} + +inline void +MachineOperand::Initialize(MachineOperandType operandType, + Value* _val) +{ + machineOperandType = operandType; + value = _val; +} + +inline void +MachineOperand::InitializeConst(MachineOperandType operandType, + int64_t intValue) +{ + machineOperandType = operandType; + value = NULL; + immedVal = intValue; +} + +inline void +MachineOperand::InitializeReg(unsigned int _regNum) +{ + machineOperandType = MO_Register; + vregType = MO_MachineReg; + value = NULL; + regNum = _regNum; +} + + +//--------------------------------------------------------------------------- +// class MachineInstr +// +// Purpose: +// Representation of each machine instruction. +// +// MachineOpCode must be an enum, defined separately for each target. +// E.g., It is defined in SparcInstructionSelection.h for the SPARC. +// The array MachineInstrInfo TargetMachineInstrInfo[] objects +// (indexed by opCode) provides information about each target instruction. +// +// opCodeMask is used to record variants of an instruction. +// E.g., each branch instruction on SPARC has 2 flags (i.e., 4 variants): +// ANNUL: if 1: Annul delay slot instruction. +// PREDICT-NOT-TAKEN: if 1: predict branch not taken. +// Instead of creating 4 different opcodes for BNZ, we create a single +// opcode and set bits in opCodeMask for each of these flags. +//--------------------------------------------------------------------------- + +class MachineInstr : public Unique { +private: + MachineOpCode opCode; + OpCodeMask opCodeMask; // extra bits for variants of an opcode + vector operands; // operand 0 is the result + +public: + /*ctor*/ MachineInstr (MachineOpCode _opCode, + OpCodeMask _opCodeMask = 0x0); + + /*dtor*/ virtual ~MachineInstr (); + + const MachineOpCode getOpCode () const; + + unsigned int getNumOperands () const; + + const MachineOperand& getOperand (unsigned int i) const; + + void dump (unsigned int indent = 0); + +public: + friend ostream& operator<<(ostream& os, const MachineInstr& minstr); + +public: + // Access to set the operands when building the machine instruction + void SetMachineOperand(unsigned int i, + MachineOperand::MachineOperandType operandType, + Value* _val); + void SetMachineOperand(unsigned int i, + MachineOperand::MachineOperandType operandType, + int64_t intValue); + void SetMachineOperand(unsigned int i, + unsigned int regNum); +}; + +inline const MachineOpCode +MachineInstr::getOpCode() const +{ + return opCode; +} + +inline unsigned int +MachineInstr::getNumOperands() const +{ + assert(operands.size() == TargetMachineInstrInfo[opCode].numOperands); + return operands.size(); +} + +inline const MachineOperand& +MachineInstr::getOperand(unsigned int i) const +{ + return operands[i]; +} + + +//--------------------------------------------------------------------------- +// class MachineInstructionsForVMInstr +// +// Purpose: +// Representation of the sequence of machine instructions created +// for a single VM instruction. Additionally records any temporary +// "values" used as intermediate values in this sequence. +// Note that such values should be treated as pure SSA values with +// no interpretation of their operands (i.e., as a TmpInstruction object +// which actually represents such a value). +// +//--------------------------------------------------------------------------- + +class MachineCodeForVMInstr: public vector +{ +private: + vector tempVec; + +public: + /*ctor*/ MachineCodeForVMInstr () {} + /*ctor*/ ~MachineCodeForVMInstr (); + + const vector& + getTempValues () const { return tempVec; } + + void addTempValue (Value* val) + { tempVec.push_back(val); } + + // dropAllReferences() - This function drops all references within + // temporary (hidden) instructions created in implementing the original + // VM intruction. This ensures there are no remaining "uses" within + // these hidden instructions, before the values of a method are freed. + // + // Make this inline because it has to be called from class Instruction + // and inlining it avoids a serious circurality in link order. + inline void dropAllReferences() { + for (unsigned i=0, N=tempVec.size(); i < N; i++) + if (tempVec[i]->getValueType() == Value::InstructionVal) + ((Instruction*) tempVec[i])->dropAllReferences(); + } +}; + +inline +MachineCodeForVMInstr::~MachineCodeForVMInstr() +{ + // Free the Value objects created to hold intermediate values + for (unsigned i=0, N=tempVec.size(); i < N; i++) + delete tempVec[i]; + + // Free the MachineInstr objects allocated, if any. + for (unsigned i=0, N=this->size(); i < N; i++) + delete (*this)[i]; +} + +//--------------------------------------------------------------------------- +// Target-independent utility routines for creating machine instructions +//--------------------------------------------------------------------------- + + +//------------------------------------------------------------------------ +// Function Set2OperandsFromInstr +// Function Set3OperandsFromInstr +// +// For the common case of 2- and 3-operand arithmetic/logical instructions, +// set the m/c instr. operands directly from the VM instruction's operands. +// Check whether the first or second operand is 0 and can use a dedicated +// "0" register. +// Check whether the second operand should use an immediate field or register. +// (First and third operands are never immediates for such instructions.) +// +// Arguments: +// canDiscardResult: Specifies that the result operand can be discarded +// by using the dedicated "0" +// +// op1position, op2position and resultPosition: Specify in which position +// in the machine instruction the 3 operands (arg1, arg2 +// and result) should go. +// +// RETURN VALUE: unsigned int flags, where +// flags & 0x01 => operand 1 is constant and needs a register +// flags & 0x02 => operand 2 is constant and needs a register +//------------------------------------------------------------------------ + +void Set2OperandsFromInstr (MachineInstr* minstr, + InstructionNode* vmInstrNode, + const TargetMachine& targetMachine, + bool canDiscardResult = false, + int op1Position = 0, + int resultPosition = 1); + +void Set3OperandsFromInstr (MachineInstr* minstr, + InstructionNode* vmInstrNode, + const TargetMachine& targetMachine, + bool canDiscardResult = false, + int op1Position = 0, + int op2Position = 1, + int resultPosition = 2); + +MachineOperand::MachineOperandType + ChooseRegOrImmed(Value* val, + MachineOpCode opCode, + const TargetMachine& targetMachine, + bool canUseImmed, + MachineOperand::VirtualRegisterType& getVRegType, + unsigned int& getMachineRegNum, + int64_t& getImmedValue); + +ostream& operator<<(ostream& os, const MachineInstr& minstr); + + +ostream& operator<<(ostream& os, const MachineOperand& mop); + + +//**************************************************************************/ + +#endif diff --git a/llvm/include/llvm/CodeGen/Sparc.h b/llvm/include/llvm/CodeGen/Sparc.h new file mode 100644 index 000000000000..8c3fbffbf49d --- /dev/null +++ b/llvm/include/llvm/CodeGen/Sparc.h @@ -0,0 +1,421 @@ +// $Id$ -*-c++-*- +//*************************************************************************** +// File: +// Sparc.cpp +// +// Purpose: +// +// History: +// 7/15/01 - Vikram Adve - Created +//**************************************************************************/ + +#ifndef LLVM_CODEGEN_SPARC_H +#define LLVM_CODEGEN_SPARC_H + +//************************** System Include Files **************************/ + +//*************************** User Include Files ***************************/ + +#include "llvm/Codegen/TargetMachine.h" +#include "llvm/Codegen/MachineInstr.h" + + +//************************* Opaque Declarations ****************************/ + + +//************************ Exported Constants ******************************/ + + +// OpCodeMask definitions for the Sparc V9 +// +const OpCodeMask Immed = 0x00002000; // immed or reg operand? +const OpCodeMask Annul = 0x20000000; // annul delay instr? +const OpCodeMask PredictTaken = 0x00080000; // predict branch taken? + + +//************************ Exported Data Types *****************************/ + + +//--------------------------------------------------------------------------- +// class UltraSparcMachine +// +// Purpose: +// Machine description. +// +//--------------------------------------------------------------------------- + +class UltraSparc: public TargetMachine { +public: + /*ctor*/ UltraSparc (); + /*dtor*/ virtual ~UltraSparc () {} +}; + + +//--------------------------------------------------------------------------- +// enum SparcMachineOpCode. +// const MachineInstrInfo SparcMachineInstrInfo[]. +// +// Purpose: +// Description of UltraSparc machine instructions. +// +//--------------------------------------------------------------------------- + + +enum SparcMachineOpCode { + + NOP, + + // Synthetic SPARC assembly opcodes for setting a register to a constant + SETSW, + SETUW, + + // Add or add with carry. + // Immed bit specifies if second operand is immediate(1) or register(0) + ADD, + ADDcc, + ADDC, + ADDCcc, + + // Subtract or subtract with carry. + // Immed bit specifies if second operand is immediate(1) or register(0) + SUB, + SUBcc, + SUBC, + SUBCcc, + + // Integer multiply, signed divide, unsigned divide. + // Note that the deprecated 32-bit multiply and multiply-step are not used. + MULX, + SDIVX, + UDIVX, + + // Floating point add, subtract, compare + FADDS, + FADDD, + FADDQ, + FSUBS, + FSUBD, + FSUBQ, + FCMPS, + FCMPD, + FCMPQ, + // NOTE: FCMPE{S,D,Q}: FP Compare With Exception are currently unused! + + // Floating point multiply or divide. + FMULS, + FMULD, + FMULQ, + FSMULD, + FDMULQ, + FDIVS, + FDIVD, + FDIVQ, + + // Logical operations + AND, + ANDcc, + ANDN, + ANDNcc, + OR, + ORcc, + ORN, + ORNcc, + XOR, + XORcc, + XNOR, + XNORcc, + + // Shift operations + SLL, + SRL, + SRA, + SLLX, + SRLX, + SRAX, + + // Convert from floating point to floating point formats + FSTOD, + FSTOQ, + FDTOS, + FDTOQ, + FQTOS, + FQTOD, + + // Convert from floating point to integer formats + FSTOX, + FDTOX, + FQTOX, + FSTOI, + FDTOI, + FQTOI, + + // Convert from integer to floating point formats + FXTOS, + FXTOD, + FXTOQ, + FITOS, + FITOD, + FITOQ, + + // Branch on integer comparison with zero. + // Annul bit specifies if intruction in delay slot is annulled(1) or not(0). + // PredictTaken bit hints if branch should be predicted taken(1) or not(0). + BRZ, + BRLEZ, + BRLZ, + BRNZ, + BRGZ, + BRGEZ, + + // Branch on integer condition code. + // Annul bit specifies if intruction in delay slot is annulled(1) or not(0). + // PredictTaken bit hints if branch should be predicted taken(1) or not(0). + BA, + BN, + BNE, + BE, + BG, + BLE, + BGE, + BL, + BGU, + BLEU, + BCC, + BCS, + BPOS, + BNEG, + BVC, + BVS, + + // Branch on floating point condition code. + // Annul bit specifies if intruction in delay slot is annulled(1) or not(0). + // PredictTaken bit hints if branch should be predicted taken(1) or not(0). + FBA, + FBN, + FBU, + FBG, + FBUG, + FBL, + FBUL, + FBLG, + FBNE, + FBE, + FBUE, + FBGE, + FBUGE, + FBLE, + FBULE, + FBO, + + // Load integer instructions + LDSB, + LDSH, + LDSW, + LDUB, + LDUH, + LDUW, + LDX, + + // Load floating-point instructions + LD, + LDD, // use of this for integers is deprecated for Sparc V9 + LDQ, + + // Store integer instructions + STB, + STH, + STW, + STX, + + // Store floating-point instructions + ST, + STD, + + // Call, Return, and "Jump and link" + // Immed bit specifies if second operand is immediate(1) or register(0) + CALL, + JMPL, + RETURN, + + // End-of-array marker + INVALID_OPCODE +}; + +const MachineInstrInfo SparcMachineInstrInfo[] = { + + { "NOP", 0, -1, 0, false }, + + // Synthetic SPARC assembly opcodes for setting a register to a constant + { "SETSW", 2, 1, 0, true }, // max immediate constant is ignored + { "SETUW", 2, 1, 0, false }, // max immediate constant is ignored + + // Add or add with carry. + { "ADD", 3, 2, (1 << 12) - 1, true }, + { "ADDcc", 3, 2, (1 << 12) - 1, true }, + { "ADDC", 3, 2, (1 << 12) - 1, true }, + { "ADDCcc", 3, 2, (1 << 12) - 1, true }, + + // Sub tract or subtract with carry. + { "SUB", 3, 2, (1 << 12) - 1, true }, + { "SUBcc", 3, 2, (1 << 12) - 1, true }, + { "SUBC", 3, 2, (1 << 12) - 1, true }, + { "SUBCcc", 3, 2, (1 << 12) - 1, true }, + + // Integer multiply, signed divide, unsigned divide. + // Note that the deprecated 32-bit multiply and multiply-step are not used. + { "MULX", 3, 2, (1 << 12) - 1, true }, + { "SDIVX", 3, 2, (1 << 12) - 1, true }, + { "UDIVX", 3, 2, (1 << 12) - 1, true }, + + // Floating point add, subtract, compare + { "FADDS", 3, 2, 0, false }, + { "FADDD", 3, 2, 0, false }, + { "FADDQ", 3, 2, 0, false }, + { "FSUBS", 3, 2, 0, false }, + { "FSUBD", 3, 2, 0, false }, + { "FSUBQ", 3, 2, 0, false }, + { "FCMPS", 3, 2, 0, false }, + { "FCMPD", 3, 2, 0, false }, + { "FCMPQ", 3, 2, 0, false }, + // NOTE: FCMPE{S,D,Q}: FP Compare With Exception are currently unused! + + // Floating point multiply or divide. + { "FMULS", 3, 2, 0, false }, + { "FMULD", 3, 2, 0, false }, + { "FMULQ", 3, 2, 0, false }, + { "FSMULD", 3, 2, 0, false }, + { "FDMULQ", 3, 2, 0, false }, + { "FDIVS", 3, 2, 0, false }, + { "FDIVD", 3, 2, 0, false }, + { "FDIVQ", 3, 2, 0, false }, + + // Logical operations + { "AND", 3, 2, (1 << 12) - 1, true }, + { "ANDcc", 3, 2, (1 << 12) - 1, true }, + { "ANDN", 3, 2, (1 << 12) - 1, true }, + { "ANDNcc", 3, 2, (1 << 12) - 1, true }, + { "OR", 3, 2, (1 << 12) - 1, true }, + { "ORcc", 3, 2, (1 << 12) - 1, true }, + { "ORN", 3, 2, (1 << 12) - 1, true }, + { "ORNcc", 3, 2, (1 << 12) - 1, true }, + { "XOR", 3, 2, (1 << 12) - 1, true }, + { "XORcc", 3, 2, (1 << 12) - 1, true }, + { "XNOR", 3, 2, (1 << 12) - 1, true }, + { "XNORcc", 3, 2, (1 << 12) - 1, true }, + + // Shift operations + { "SLL", 3, 2, (1 << 5) - 1, true }, + { "SRL", 3, 2, (1 << 5) - 1, true }, + { "SRA", 3, 2, (1 << 5) - 1, true }, + { "SLLX", 3, 2, (1 << 6) - 1, true }, + { "SRLX", 3, 2, (1 << 6) - 1, true }, + { "SRAX", 3, 2, (1 << 6) - 1, true }, + + // Convert from floating point to floating point formats + { "FSTOD", 2, 1, 0, false }, + { "FSTOQ", 2, 1, 0, false }, + { "FDTOS", 2, 1, 0, false }, + { "FDTOQ", 2, 1, 0, false }, + { "FQTOS", 2, 1, 0, false }, + { "FQTOD", 2, 1, 0, false }, + + // Convert from floating point to integer formats + { "FSTOX", 2, 1, 0, false }, + { "FDTOX", 2, 1, 0, false }, + { "FQTOX", 2, 1, 0, false }, + { "FSTOI", 2, 1, 0, false }, + { "FDTOI", 2, 1, 0, false }, + { "FQTOI", 2, 1, 0, false }, + + // Convert from integer to floating point formats + { "FXTOS", 2, 1, 0, false }, + { "FXTOD", 2, 1, 0, false }, + { "FXTOQ", 2, 1, 0, false }, + { "FITOS", 2, 1, 0, false }, + { "FITOD", 2, 1, 0, false }, + { "FITOQ", 2, 1, 0, false }, + + // Branch on integer comparison with zero. + { "BRZ", 2, -1, (1 << 15) - 1, true }, + { "BRLEZ", 2, -1, (1 << 15) - 1, true }, + { "BRLZ", 2, -1, (1 << 15) - 1, true }, + { "BRNZ", 2, -1, (1 << 15) - 1, true }, + { "BRGZ", 2, -1, (1 << 15) - 1, true }, + { "BRGEZ", 2, -1, (1 << 15) - 1, true }, + + // Branch on condition code. + { "BA", 1, -1, (1 << 21) - 1, true }, + { "BN", 1, -1, (1 << 21) - 1, true }, + { "BNE", 1, -1, (1 << 21) - 1, true }, + { "BE", 1, -1, (1 << 21) - 1, true }, + { "BG", 1, -1, (1 << 21) - 1, true }, + { "BLE", 1, -1, (1 << 21) - 1, true }, + { "BGE", 1, -1, (1 << 21) - 1, true }, + { "BL", 1, -1, (1 << 21) - 1, true }, + { "BGU", 1, -1, (1 << 21) - 1, true }, + { "BLEU", 1, -1, (1 << 21) - 1, true }, + { "BCC", 1, -1, (1 << 21) - 1, true }, + { "BCS", 1, -1, (1 << 21) - 1, true }, + { "BPOS", 1, -1, (1 << 21) - 1, true }, + { "BNEG", 1, -1, (1 << 21) - 1, true }, + { "BVC", 1, -1, (1 << 21) - 1, true }, + { "BVS", 1, -1, (1 << 21) - 1, true }, + + // Branch on floating point condition code. + // Annul bit specifies if intruction in delay slot is annulled(1) or not(0). + // PredictTaken bit hints if branch should be predicted taken(1) or not(0). + // The first argument is the FCCn register (0 <= n <= 3). + { "FBA", 2, -1, (1 << 18) - 1, true }, + { "FBN", 2, -1, (1 << 18) - 1, true }, + { "FBU", 2, -1, (1 << 18) - 1, true }, + { "FBG", 2, -1, (1 << 18) - 1, true }, + { "FBUG", 2, -1, (1 << 18) - 1, true }, + { "FBL", 2, -1, (1 << 18) - 1, true }, + { "FBUL", 2, -1, (1 << 18) - 1, true }, + { "FBLG", 2, -1, (1 << 18) - 1, true }, + { "FBNE", 2, -1, (1 << 18) - 1, true }, + { "FBE", 2, -1, (1 << 18) - 1, true }, + { "FBUE", 2, -1, (1 << 18) - 1, true }, + { "FBGE", 2, -1, (1 << 18) - 1, true }, + { "FBUGE", 2, -1, (1 << 18) - 1, true }, + { "FBLE", 2, -1, (1 << 18) - 1, true }, + { "FBULE", 2, -1, (1 << 18) - 1, true }, + { "FBO", 2, -1, (1 << 18) - 1, true }, + + // Load integer instructions + { "LDSB", 3, 2, (1 << 12) - 1, true }, + { "LDSH", 3, 2, (1 << 12) - 1, true }, + { "LDSW", 3, 2, (1 << 12) - 1, true }, + { "LDUB", 3, 2, (1 << 12) - 1, true }, + { "LDUH", 3, 2, (1 << 12) - 1, true }, + { "LDUW", 3, 2, (1 << 12) - 1, true }, + { "LDX", 3, 2, (1 << 12) - 1, true }, + + // Load floating-point instructions + { "LD", 3, 2, (1 << 12) - 1, true }, + { "LDD", 3, 2, (1 << 12) - 1, true }, + { "LDQ", 3, 2, (1 << 12) - 1, true }, + + // Store integer instructions + { "STB", 3, -1, (1 << 12) - 1, true }, + { "STH", 3, -1, (1 << 12) - 1, true }, + { "STW", 3, -1, (1 << 12) - 1, true }, + { "STX", 3, -1, (1 << 12) - 1, true }, + + // Store floating-point instructions + { "ST", 3, -1, (1 << 12) - 1, true }, + { "STD", 3, -1, (1 << 12) - 1, true }, + + // Call, Return and "Jump and link" + { "CALL", 1, -1, (1 << 29) - 1, true }, + { "JMPL", 3, -1, (1 << 12) - 1, true }, + { "RETURN", 2, -1, 0, false }, + + // End-of-array marker + { "INVALID_SPARC_OPCODE", 0, -1, 0, false } +}; + + +/***************************************************************************/ + +#endif diff --git a/llvm/include/llvm/CodeGen/TargetMachine.h b/llvm/include/llvm/CodeGen/TargetMachine.h new file mode 100644 index 000000000000..72545f88e96d --- /dev/null +++ b/llvm/include/llvm/CodeGen/TargetMachine.h @@ -0,0 +1,111 @@ +// $Id$ -*-c++-*- +//*************************************************************************** +// File: +// TargetMachine.h +// +// Purpose: +// +// History: +// 7/12/01 - Vikram Adve - Created +//**************************************************************************/ + +#ifndef LLVM_CODEGEN_TARGETMACHINE_H +#define LLVM_CODEGEN_TARGETMACHINE_H + +//************************** System Include Files **************************/ + +//*************************** User Include Files ***************************/ + +#include "llvm/Support/Unique.h" +#include "llvm/Tools/DataTypes.h" + +//************************* Opaque Declarations ****************************/ + +class Type; +class StructType; +class MachineInstrInfo; + + +//************************ Exported Data Types *****************************/ + + +//--------------------------------------------------------------------------- +// Data types used to define information about a single machine instruction +//--------------------------------------------------------------------------- + +typedef int MachineOpCode; +typedef int OpCodeMask; + + +// struct MachineInstrInfo: +// Predefined information about each machine instruction. +// +struct MachineInstrInfo { + string opCodeString; // Assembly language mnemonic for the opcode. + unsigned int numOperands; // Number of arguments for the instruction. + int resultPos; // Position of the result; -1 if no result + unsigned int maxImmedConst; // Largest +ve constant in IMMMED field or 0. + bool immedIsSignExtended; // Is the IMMED field sign-extended? If so, + // smallest -ve value is -(maxImmedConst+1). + + + // Check if the specified constant fits in the immediate field + // of this machine instruction + // + bool constantFitsInImmedField (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. + // + inline uint64_t maxImmedConstant(bool& isSignExtended) const { + isSignExtended = immedIsSignExtended; + return maxImmedConst; } +}; + +// Global variable holding an array of the above structures. +// This needs to be defined separately for each target machine. +// +extern const MachineInstrInfo* TargetMachineInstrInfo; + + +//--------------------------------------------------------------------------- +// class TargetMachine +// +// Purpose: +// Machine description. +// +//--------------------------------------------------------------------------- + +class TargetMachine: public Unique { +public: + int optSizeForSubWordData; + int intSize; + int longSize; + int floatSize; + int doubleSize; + int longDoubleSize; + int pointerSize; + int minMemOpWordSize; + int maxAtomicMemOpWordSize; + + // Description of machine instructions (array indexed by machine opcode) + const MachineInstrInfo* machineInstrInfo; + + // Register information. This needs to be reorganized into a single class. + int zeroRegNum; // register that gives 0 if any (-1 if none) + +public: + /*ctor*/ TargetMachine () {} + /*dtor*/ virtual ~TargetMachine () {} + + virtual unsigned int findOptimalStorageSize (const Type* ty) const; + + virtual unsigned int* findOptimalMemberOffsets(const StructType* stype)const; +}; + +//**************************************************************************/ + +#endif