diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 36e11bc6d29..bb2f930d5f5 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -15,11 +15,15 @@ #ifndef LLVM_CODEGEN_MACHINEINSTR_H #define LLVM_CODEGEN_MACHINEINSTR_H +#include #include "llvm/CodeGen/InstrForest.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/NonCopyable.h" #include "llvm/CodeGen/TargetMachine.h" +template class ValOpIterator; + + //--------------------------------------------------------------------------- // class MachineOperand // @@ -56,56 +60,78 @@ //--------------------------------------------------------------------------- class MachineOperand { -public: - friend ostream& operator<<(ostream& os, const MachineOperand& mop); - public: enum MachineOperandType { - MO_Register, + MO_VirtualRegister, // virtual register for *value + MO_MachineRegister, // pre-assigned machine register `regNum' MO_CCRegister, MO_SignExtendedImmed, MO_UnextendedImmed, MO_PCRelativeDisp, }; - enum VirtualRegisterType { - MO_VirtualReg, // virtual register for *value - MO_MachineReg // pre-assigned machine register `regNum' +private: + MachineOperandType opType; + + union { + Value* value; // BasicBlockVal for a label operand. + // ConstantVal for a non-address immediate. + // Virtual register for an SSA operand, + // including hidden operands required for + // the generated machine code. + + unsigned int regNum; // register number for an explicit register + + int64_t immedVal; // constant value for an explicit constant }; - 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 - +public: /*ctor*/ MachineOperand (); /*ctor*/ MachineOperand (MachineOperandType operandType, Value* _val); /*copy ctor*/ MachineOperand (const MachineOperand&); /*dtor*/ ~MachineOperand () {} + // Accessor methods. Caller is responsible for checking the + // operand type before invoking the corresponding accessor. + // + MachineOperandType getOperandType () const { + return opType; + } + Value* getVRegValue () const { + assert(opType == MO_VirtualRegister || opType == MO_CCRegister); + return value; + } + unsigned int getMachineRegNum() const { + assert(opType == MO_MachineRegister); + return regNum; + } + int64_t getImmedValue () const { + assert(opType >= MO_SignExtendedImmed || opType <= MO_PCRelativeDisp); + return immedVal; + } + +public: + friend ostream& operator<<(ostream& os, const MachineOperand& mop); + +private: // These functions are provided so that a vector of operands can be // statically allocated and individual ones can be initialized later. + // Give class MachineInstr gets access to these functions. // void Initialize (MachineOperandType operandType, Value* _val); void InitializeConst (MachineOperandType operandType, int64_t intValue); void InitializeReg (unsigned int regNum); + + friend class MachineInstr; }; inline MachineOperand::MachineOperand() - : machineOperandType(MO_Register), - vregType(MO_VirtualReg), + : opType(MO_VirtualRegister), value(NULL), regNum(0), immedVal(0) @@ -114,8 +140,7 @@ MachineOperand::MachineOperand() inline MachineOperand::MachineOperand(MachineOperandType operandType, Value* _val) - : machineOperandType(operandType), - vregType(MO_VirtualReg), + : opType(operandType), value(_val), regNum(0), immedVal(0) @@ -123,19 +148,24 @@ MachineOperand::MachineOperand(MachineOperandType operandType, inline MachineOperand::MachineOperand(const MachineOperand& mo) - : machineOperandType(mo.machineOperandType), - vregType(mo.vregType), - value(mo.value), - regNum(mo.regNum), - immedVal(mo.immedVal) + : opType(mo.opType) { + switch(opType) { + case MO_VirtualRegister: + case MO_CCRegister: value = mo.value; break; + case MO_MachineRegister: regNum = mo.regNum; break; + case MO_SignExtendedImmed: + case MO_UnextendedImmed: + case MO_PCRelativeDisp: immedVal = mo.immedVal; break; + default: assert(0); + } } inline void MachineOperand::Initialize(MachineOperandType operandType, Value* _val) { - machineOperandType = operandType; + opType = operandType; value = _val; } @@ -143,7 +173,7 @@ inline void MachineOperand::InitializeConst(MachineOperandType operandType, int64_t intValue) { - machineOperandType = operandType; + opType = operandType; value = NULL; immedVal = intValue; } @@ -151,8 +181,7 @@ MachineOperand::InitializeConst(MachineOperandType operandType, inline void MachineOperand::InitializeReg(unsigned int _regNum) { - machineOperandType = MO_Register; - vregType = MO_MachineReg; + opType = MO_MachineRegister; value = NULL; regNum = _regNum; } @@ -166,8 +195,6 @@ MachineOperand::InitializeReg(unsigned int _regNum) // // 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): @@ -181,12 +208,15 @@ class MachineInstr : public NonCopyable { private: MachineOpCode opCode; OpCodeMask opCodeMask; // extra bits for variants of an opcode - vector operands; // operand 0 is the result + vector operands; + +public: + typedef ValOpIterator val_op_const_iterator; + typedef ValOpIterator< MachineInstr, Value> val_op_iterator; public: /*ctor*/ MachineInstr (MachineOpCode _opCode, OpCodeMask _opCodeMask = 0x0); - inline ~MachineInstr () {} const MachineOpCode getOpCode () const; @@ -194,11 +224,14 @@ public: unsigned int getNumOperands () const; const MachineOperand& getOperand (unsigned int i) const; + MachineOperand& getOperand (unsigned int i); void dump (unsigned int indent = 0); public: friend ostream& operator<<(ostream& os, const MachineInstr& minstr); + friend val_op_const_iterator; + friend val_op_iterator; public: // Access to set the operands when building the machine instruction @@ -221,10 +254,15 @@ MachineInstr::getOpCode() const inline unsigned int MachineInstr::getNumOperands() const { - assert(operands.size() == TargetMachineInstrInfo[opCode].numOperands); return operands.size(); } +inline MachineOperand& +MachineInstr::getOperand(unsigned int i) +{ + return operands[i]; +} + inline const MachineOperand& MachineInstr::getOperand(unsigned int i) const { @@ -232,6 +270,38 @@ MachineInstr::getOperand(unsigned int i) const } +template +class ValOpIterator : public std::forward_iterator<_V, ptrdiff_t> { +private: + unsigned int i; + int resultPos; + _MI*& minstr; + + inline void skipToNextVal() { + while (i < minstr->getNumOperands() + && minstr->getOperand(i).getOperandType() != MachineOperand::MO_VirtualRegister + && minstr->getOperand(i).getOperandType() != MachineOperand::MO_CCRegister) + ++i; + } + +public: + typedef ValOpIterator<_MI, _V> _Self; + + inline ValOpIterator(_MI* _minstr) : i(0), minstr(_minstr) { + resultPos = TargetInstrDescriptors[minstr->opCode].resultPos; + skipToNextVal(); + }; + + inline _V* operator*() const { return minstr->getOperand(i).getVRegValue();} + inline _V* operator->() const { return operator*(); } + inline bool isDef () const { return (((int) i) == resultPos); } + inline bool done () const { return (i == minstr->getNumOperands()); } + + inline _Self& operator++() { i++; skipToNextVal(); return *this; } + inline _Self operator++(int) { _Self tmp = *this; ++*this; return tmp; } +}; + + //--------------------------------------------------------------------------- // class MachineInstructionsForVMInstr // @@ -332,12 +402,11 @@ void Set3OperandsFromInstr (MachineInstr* minstr, MachineOperand::MachineOperandType ChooseRegOrImmed(Value* val, - MachineOpCode opCode, - const TargetMachine& targetMachine, - bool canUseImmed, - MachineOperand::VirtualRegisterType& getVRegType, - unsigned int& getMachineRegNum, - int64_t& getImmedValue); + MachineOpCode opCode, + const TargetMachine& targetMachine, + bool canUseImmed, + unsigned int& getMachineRegNum, + int64_t& getImmedValue); ostream& operator<<(ostream& os, const MachineInstr& minstr); diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index c43b022bb1d..64fcaa05771 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -20,28 +20,11 @@ //************************ Class Implementations **************************/ -bool -MachineInstrInfo::constantFitsInImmedField(int64_t intValue) const -{ - // First, check if opCode has an immed field. - bool isSignExtended; - uint64_t maxImmedValue = this->maxImmedConstant(isSignExtended); - if (maxImmedValue != 0) - { - // Now check if the constant fits - if (intValue <= (int64_t) maxImmedValue && - intValue >= -((int64_t) maxImmedValue+1)) - return true; - } - - return false; -} - MachineInstr::MachineInstr(MachineOpCode _opCode, OpCodeMask _opCodeMask) : opCode(_opCode), opCodeMask(_opCodeMask), - operands(TargetMachineInstrInfo[_opCode].numOperands) + operands(TargetInstrDescriptors[_opCode].numOperands) { } @@ -50,7 +33,7 @@ MachineInstr::SetMachineOperand(unsigned int i, MachineOperand::MachineOperandType operandType, Value* _val) { - assert(i < TargetMachineInstrInfo[opCode].numOperands); + assert(i < operands.size()); operands[i].Initialize(operandType, _val); } @@ -59,7 +42,7 @@ MachineInstr::SetMachineOperand(unsigned int i, MachineOperand::MachineOperandType operandType, int64_t intValue) { - assert(i < TargetMachineInstrInfo[opCode].numOperands); + assert(i < operands.size()); operands[i].InitializeConst(operandType, intValue); } @@ -67,7 +50,7 @@ void MachineInstr::SetMachineOperand(unsigned int i, unsigned int regNum) { - assert(i < TargetMachineInstrInfo[opCode].numOperands); + assert(i < operands.size()); operands[i].InitializeReg(regNum); } @@ -83,11 +66,22 @@ MachineInstr::dump(unsigned int indent) ostream& operator<< (ostream& os, const MachineInstr& minstr) { - os << TargetMachineInstrInfo[minstr.opCode].opCodeString; + os << TargetInstrDescriptors[minstr.opCode].opCodeString; for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++) os << "\t" << minstr.getOperand(i); +#undef DEBUG_VAL_OP_ITERATOR +#ifdef DEBUG_VAL_OP_ITERATOR + os << endl << "\tValue operands are: "; + for (MachineInstr::val_op_const_iterator vo(&minstr); ! vo.done(); ++vo) + { + const Value* val = *vo; + os << val << (vo.isDef()? "(def), " : ", "); + } + os << endl; +#endif + return os; } @@ -95,19 +89,17 @@ ostream& operator<< (ostream& os, const MachineOperand& mop) { strstream regInfo; - if (mop.machineOperandType == MachineOperand::MO_Register) - { - if (mop.vregType == MachineOperand::MO_VirtualReg) - regInfo << "(val " << mop.value << ")" << ends; - else - regInfo << "(" << mop.regNum << ")" << ends; - } - else if (mop.machineOperandType == MachineOperand::MO_CCRegister) + if (mop.opType == MachineOperand::MO_VirtualRegister) + regInfo << "(val " << mop.value << ")" << ends; + else if (mop.opType == MachineOperand::MO_MachineRegister) + regInfo << "(" << mop.regNum << ")" << ends; + else if (mop.opType == MachineOperand::MO_CCRegister) regInfo << "(val " << mop.value << ")" << ends; - switch(mop.machineOperandType) + switch(mop.opType) { - case MachineOperand::MO_Register: + case MachineOperand::MO_VirtualRegister: + case MachineOperand::MO_MachineRegister: os << "%reg" << regInfo.str(); free(regInfo.str()); break; @@ -169,21 +161,22 @@ operator<< (ostream& os, const MachineOperand& mop) void Set2OperandsFromInstr(MachineInstr* minstr, InstructionNode* vmInstrNode, - const TargetMachine& targetMachine, + const TargetMachine& target, bool canDiscardResult, int op1Position, int resultPosition) { - Set3OperandsFromInstr(minstr, vmInstrNode, targetMachine, + Set3OperandsFromInstr(minstr, vmInstrNode, target, canDiscardResult, op1Position, /*op2Position*/ -1, resultPosition); } - +#undef REVERT_TO_EXPLICIT_CONSTANT_CHECKS +#ifdef REVERT_TO_EXPLICIT_CONSTANT_CHECKS unsigned Set3OperandsFromInstrJUNK(MachineInstr* minstr, InstructionNode* vmInstrNode, - const TargetMachine& targetMachine, + const TargetMachine& target, bool canDiscardResult, int op1Position, int op2Position, @@ -198,16 +191,16 @@ Set3OperandsFromInstrJUNK(MachineInstr* minstr, Value* op1Value = vmInstrNode->leftChild()->getValue(); bool isValidConstant; int64_t intValue = GetConstantValueAsSignedInt(op1Value, isValidConstant); - if (isValidConstant && intValue == 0 && targetMachine.zeroRegNum >= 0) - minstr->SetMachineOperand(op1Position, /*regNum*/ targetMachine.zeroRegNum); + if (isValidConstant && intValue == 0 && target.zeroRegNum >= 0) + minstr->SetMachineOperand(op1Position, /*regNum*/ target.zeroRegNum); else { if (op1Value->getValueType() == Value::ConstantVal) {// value is constant and must be loaded from constant pool returnFlags = returnFlags | (1 << op1Position); } - minstr->SetMachineOperand(op1Position, MachineOperand::MO_Register, - op1Value); + minstr->SetMachineOperand(op1Position,MachineOperand::MO_VirtualRegister, + op1Value); } // Check if operand 2 (if any) fits in the immediate field of the instruction, @@ -216,46 +209,45 @@ Set3OperandsFromInstrJUNK(MachineInstr* minstr, { Value* op2Value = vmInstrNode->rightChild()->getValue(); int64_t immedValue; - MachineOperand::VirtualRegisterType vregType; unsigned int machineRegNum; MachineOperand::MachineOperandType - op2type = ChooseRegOrImmed(op2Value, minstr->getOpCode(),targetMachine, + op2type = ChooseRegOrImmed(op2Value, minstr->getOpCode(), target, /*canUseImmed*/ true, - vregType, machineRegNum, immedValue); + machineRegNum, immedValue); - if (op2type == MachineOperand::MO_Register) + if (op2type == MachineOperand::MO_MachineRegister) + minstr->SetMachineOperand(op2Position, machineRegNum); + else if (op2type == MachineOperand::MO_VirtualRegister) { - if (vregType == MachineOperand::MO_MachineReg) - minstr->SetMachineOperand(op2Position, machineRegNum); - else - { - if (op2Value->getValueType() == Value::ConstantVal) - {// value is constant and must be loaded from constant pool - returnFlags = returnFlags | (1 << op2Position); - } - minstr->SetMachineOperand(op2Position, op2type, op2Value); + if (op2Value->getValueType() == Value::ConstantVal) + {// value is constant and must be loaded from constant pool + returnFlags = returnFlags | (1 << op2Position); } + minstr->SetMachineOperand(op2Position, op2type, op2Value); } else - minstr->SetMachineOperand(op2Position, op2type, immedValue); + { + assert(op2type != MO_CCRegister); + minstr->SetMachineOperand(op2Position, op2type, immedValue); + } } // If operand 3 (result) can be discarded, use a dead register if one exists - if (canDiscardResult && targetMachine.zeroRegNum >= 0) - minstr->SetMachineOperand(resultPosition, targetMachine.zeroRegNum); + if (canDiscardResult && target.zeroRegNum >= 0) + minstr->SetMachineOperand(resultPosition, target.zeroRegNum); else - minstr->SetMachineOperand(resultPosition, MachineOperand::MO_Register, - vmInstrNode->getValue()); + minstr->SetMachineOperand(resultPosition, MachineOperand::MO_VirtualRegister, vmInstrNode->getValue()); return returnFlags; } +#endif void Set3OperandsFromInstr(MachineInstr* minstr, InstructionNode* vmInstrNode, - const TargetMachine& targetMachine, + const TargetMachine& target, bool canDiscardResult, int op1Position, int op2Position, @@ -265,34 +257,32 @@ Set3OperandsFromInstr(MachineInstr* minstr, assert(resultPosition >= 0); // operand 1 - minstr->SetMachineOperand(op1Position, MachineOperand::MO_Register, + minstr->SetMachineOperand(op1Position, MachineOperand::MO_VirtualRegister, vmInstrNode->leftChild()->getValue()); // operand 2 (if any) if (op2Position >= 0) - minstr->SetMachineOperand(op2Position, MachineOperand::MO_Register, + minstr->SetMachineOperand(op2Position, MachineOperand::MO_VirtualRegister, vmInstrNode->rightChild()->getValue()); // result operand: if it can be discarded, use a dead register if one exists - if (canDiscardResult && targetMachine.zeroRegNum >= 0) - minstr->SetMachineOperand(resultPosition, targetMachine.zeroRegNum); + if (canDiscardResult && target.zeroRegNum >= 0) + minstr->SetMachineOperand(resultPosition, target.zeroRegNum); else - minstr->SetMachineOperand(resultPosition, MachineOperand::MO_Register, - vmInstrNode->getValue()); + minstr->SetMachineOperand(resultPosition, MachineOperand::MO_VirtualRegister, vmInstrNode->getValue()); } MachineOperand::MachineOperandType ChooseRegOrImmed(Value* val, MachineOpCode opCode, - const TargetMachine& targetMachine, + const TargetMachine& target, bool canUseImmed, - MachineOperand::VirtualRegisterType& getVRegType, unsigned int& getMachineRegNum, int64_t& getImmedValue) { - MachineOperand::MachineOperandType opType = MachineOperand::MO_Register; - getVRegType = MachineOperand::MO_VirtualReg; + MachineOperand::MachineOperandType opType = + MachineOperand::MO_VirtualRegister; getMachineRegNum = 0; getImmedValue = 0; @@ -311,13 +301,13 @@ ChooseRegOrImmed(Value* val, if (isValidConstant) { - if (intValue == 0 && targetMachine.zeroRegNum >= 0) + if (intValue == 0 && target.zeroRegNum >= 0) { - getVRegType = MachineOperand::MO_MachineReg; - getMachineRegNum = targetMachine.zeroRegNum; + opType = MachineOperand::MO_MachineRegister; + getMachineRegNum = target.zeroRegNum; } else if (canUseImmed && - targetMachine.machineInstrInfo[opCode].constantFitsInImmedField(intValue)) + target.getInstrInfo().constantFitsInImmedField(opCode,intValue)) { opType = MachineOperand::MO_SignExtendedImmed; getImmedValue = intValue;