-//===-- llvm/CodeGen/MachineInstr.h - MachineInstr class ---------*- C++ -*--=//
+//===-- llvm/CodeGen/MachineInstr.h - MachineInstr class --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the MachineInstr class, which is the
-// basic representation for all target dependant machine instructions used by
+// basic representation for all target dependent machine instructions used by
// the back end.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_MACHINEINSTR_H
#define LLVM_CODEGEN_MACHINEINSTR_H
-#include "llvm/Target/MRegisterInfo.h"
#include "Support/Annotation.h"
#include "Support/iterator"
-#include <set>
+#include <vector>
+
+namespace llvm {
class Value;
class Function;
class TargetMachine;
class GlobalValue;
-typedef int MachineOpCode;
+template <typename T> class ilist_traits;
+template <typename T> class ilist;
-//===----------------------------------------------------------------------===//
-/// Special flags on instructions that modify the opcode.
-/// These flags are unused for now, but having them enforces that some
-/// changes will be needed if they are used.
-///
-enum MachineOpCodeFlags {
- AnnulFlag, /// 1 if annul bit is set on a branch
- PredTakenFlag, /// 1 if branch should be predicted taken
- PredNotTakenFlag /// 1 if branch should be predicted not taken
-};
+typedef short MachineOpCode;
//===----------------------------------------------------------------------===//
/// MOTy - MachineOperandType - This namespace contains an enum that describes
private:
// Bit fields of the flags variable used for different operand properties
enum {
- DEFONLYFLAG = 0x01, // this is a def but not a use of the operand
- DEFUSEFLAG = 0x02, // this is both a def and a use
+ DEFFLAG = 0x01, // this is a def of the operand
+ USEFLAG = 0x02, // this is a use of the operand
HIFLAG32 = 0x04, // operand is %hi32(value_or_immedVal)
LOFLAG32 = 0x08, // operand is %lo32(value_or_immedVal)
HIFLAG64 = 0x10, // operand is %hi64(value_or_immedVal)
LOFLAG64 = 0x20, // operand is %lo64(value_or_immedVal)
PCRELATIVE = 0x40, // Operand is relative to PC, not a global address
-
- USEDEFMASK = 0x03,
};
private:
int regNum; // register number for an explicit register
// will be set for a value after reg allocation
private:
- MachineOperand()
- : immedVal(0),
- flags(0),
- opType(MO_VirtualRegister),
- regNum(-1) {}
-
- MachineOperand(int64_t ImmVal, MachineOperandType OpTy)
+ MachineOperand(int64_t ImmVal = 0, MachineOperandType OpTy = MO_VirtualRegister)
: immedVal(ImmVal),
flags(0),
opType(OpTy),
opType(OpTy),
regNum(Reg) {
switch (UseTy) {
- case MOTy::Use: flags = 0; break;
- case MOTy::Def: flags = DEFONLYFLAG; break;
- case MOTy::UseAndDef: flags = DEFUSEFLAG; break;
+ case MOTy::Use: flags = USEFLAG; break;
+ case MOTy::Def: flags = DEFFLAG; break;
+ case MOTy::UseAndDef: flags = DEFFLAG | USEFLAG; break;
default: assert(0 && "Invalid value for UseTy!");
}
}
bool isPCRelative = false)
: value(V), opType(OpTy), regNum(-1) {
switch (UseTy) {
- case MOTy::Use: flags = 0; break;
- case MOTy::Def: flags = DEFONLYFLAG; break;
- case MOTy::UseAndDef: flags = DEFUSEFLAG; break;
+ case MOTy::Use: flags = USEFLAG; break;
+ case MOTy::Def: flags = DEFFLAG; break;
+ case MOTy::UseAndDef: flags = DEFFLAG | USEFLAG; break;
default: assert(0 && "Invalid value for UseTy!");
}
if (isPCRelative) flags |= PCRELATIVE;
}
const MachineOperand &operator=(const MachineOperand &MO) {
+ if (isExternalSymbol()) // if old operand had a symbol name,
+ delete SymbolName; // release old memory
immedVal = MO.immedVal;
flags = MO.flags;
opType = MO.opType;
return *this;
}
- // Accessor methods. Caller is responsible for checking the
- // operand type before invoking the corresponding accessor.
- //
+ /// getType - Returns the MachineOperandType for this operand.
+ ///
MachineOperandType getType() const { return opType; }
+ /// getUseType - Returns the MachineOperandUseType of this operand.
+ ///
+ MOTy::UseType getUseType() const {
+ return isUse() ^ isDef() ? MOTy::UseAndDef :
+ (isUse() ? MOTy::Use : MOTy::Def);
+ }
+
/// isPCRelative - This returns the value of the PCRELATIVE flag, which
/// indicates whether this operand should be emitted as a PC relative value
/// instead of a global address. This is used for operands of the forms:
///
bool isPCRelative() const { return (flags & PCRELATIVE) != 0; }
-
- // This is to finally stop caring whether we have a virtual or machine
- // register -- an easier interface is to simply call both virtual and machine
- // registers essentially the same, yet be able to distinguish when
- // necessary. Thus the instruction selector can just add registers without
- // abandon, and the register allocator won't be confused.
- bool isVirtualRegister() const {
- return (opType == MO_VirtualRegister || opType == MO_MachineRegister)
- && regNum >= MRegisterInfo::FirstVirtualRegister;
- }
- bool isPhysicalRegister() const {
- return (opType == MO_VirtualRegister || opType == MO_MachineRegister)
- && (unsigned)regNum < MRegisterInfo::FirstVirtualRegister;
+ /// isRegister - Return true if this operand is a register operand. The X86
+ /// backend currently can't decide whether to use MO_MR or MO_VR to represent
+ /// them, so we accept both.
+ ///
+ /// Note: The sparc backend should not use this method.
+ ///
+ bool isRegister() const {
+ return opType == MO_MachineRegister || opType == MO_VirtualRegister;
}
- bool isRegister() const { return isVirtualRegister() || isPhysicalRegister();}
- bool isMachineRegister() const { return !isVirtualRegister(); }
+
bool isMachineBasicBlock() const { return opType == MO_MachineBasicBlock; }
bool isPCRelativeDisp() const { return opType == MO_PCRelativeDisp; }
bool isImmediate() const {
return regNum;
}
int64_t getImmedValue() const { assert(isImmediate()); return immedVal; }
+ void setImmedValue(int64_t ImmVal) { assert(isImmediate()); immedVal=ImmVal; }
+
MachineBasicBlock *getMachineBasicBlock() const {
assert(isMachineBasicBlock() && "Can't get MBB in non-MBB operand!");
return MBB;
return *SymbolName;
}
- bool opIsUse () const { return (flags & USEDEFMASK) == 0; }
- bool opIsDefOnly () const { return flags & DEFONLYFLAG; }
- bool opIsDefAndUse () const { return flags & DEFUSEFLAG; }
- bool opHiBits32 () const { return flags & HIFLAG32; }
- bool opLoBits32 () const { return flags & LOFLAG32; }
- bool opHiBits64 () const { return flags & HIFLAG64; }
- bool opLoBits64 () const { return flags & LOFLAG64; }
+ bool isUse () const { return flags & USEFLAG; }
+ MachineOperand& setUse () { flags |= USEFLAG; return *this; }
+ bool isDef () const { return flags & DEFFLAG; }
+ MachineOperand& setDef () { flags |= DEFFLAG; return *this; }
+ bool isHiBits32 () const { return flags & HIFLAG32; }
+ bool isLoBits32 () const { return flags & LOFLAG32; }
+ bool isHiBits64 () const { return flags & HIFLAG64; }
+ bool isLoBits64 () const { return flags & LOFLAG64; }
// used to check if a machine register has been allocated to this operand
bool hasAllocatedReg() const {
}
// used to get the reg number if when one is allocated
- int getAllocatedRegNum() const {
+ unsigned getReg() const {
assert(hasAllocatedReg());
return regNum;
}
// ********** TODO: get rid of this duplicate code! ***********
- unsigned getReg() const {
- return getAllocatedRegNum();
+ void setReg(unsigned Reg) {
+ assert(hasAllocatedReg() && "This operand cannot have a register number!");
+ regNum = Reg;
}
friend std::ostream& operator<<(std::ostream& os, const MachineOperand& mop);
//===----------------------------------------------------------------------===//
class MachineInstr {
- int opCode; // the opcode
- unsigned opCodeFlags; // flags modifying instrn behavior
+ short Opcode; // the opcode
+ unsigned char numImplicitRefs; // number of implicit operands
std::vector<MachineOperand> operands; // the operands
- unsigned numImplicitRefs; // number of implicit operands
-
- // regsUsed - all machine registers used for this instruction, including regs
- // used to save values across the instruction. This is a bitset of registers.
- std::set<int> regsUsed;
-
+ MachineInstr* prev, *next; // links for our intrusive list
+ MachineBasicBlock* parent; // pointer to the owning basic block
// OperandComplete - Return true if it's illegal to add a new operand
bool OperandsComplete() const;
MachineInstr(const MachineInstr &); // DO NOT IMPLEMENT
void operator=(const MachineInstr&); // DO NOT IMPLEMENT
+
+private:
+ // Intrusive list support
+ //
+ friend class ilist_traits<MachineInstr>;
+
public:
- MachineInstr(int Opcode, unsigned numOperands);
+ MachineInstr(short Opcode, unsigned numOperands);
/// MachineInstr ctor - This constructor only does a _reserve_ of the
/// operands, not a resize for them. It is expected that if you use this that
/// you call add* methods below to fill up the operands, instead of the Set
/// methods. Eventually, the "resizing" ctors will be phased out.
///
- MachineInstr(int Opcode, unsigned numOperands, bool XX, bool YY);
+ MachineInstr(short Opcode, unsigned numOperands, bool XX, bool YY);
/// MachineInstr ctor - Work exactly the same as the ctor above, except that
/// the MachineInstr is created and added to the end of the specified basic
/// block.
///
- MachineInstr(MachineBasicBlock *MBB, int Opcode, unsigned numOps);
+ MachineInstr(MachineBasicBlock *MBB, short Opcode, unsigned numOps);
+ ~MachineInstr();
- // The opcode.
- //
- const int getOpcode() const { return opCode; }
- const int getOpCode() const { return opCode; }
+ const MachineBasicBlock* getParent() const { return parent; }
+ MachineBasicBlock* getParent() { return parent; }
- // Opcode flags.
- //
- unsigned getOpCodeFlags() const { return opCodeFlags; }
+ /// Accessors for opcode.
+ ///
+ const int getOpcode() const { return Opcode; }
- //
- // Access to explicit operands of the instruction
- //
+ /// Access to explicit operands of the instruction.
+ ///
unsigned getNumOperands() const { return operands.size() - numImplicitRefs; }
const MachineOperand& getOperand(unsigned i) const {
++numImplicitRefs;
addRegOperand(V, isDef, isDefAndUse);
}
- void setImplicitRef(unsigned i, Value* V, bool isDef=false,
- bool isDefAndUse=false) {
+ void setImplicitRef(unsigned i, Value* V) {
assert(i < getNumImplicitRefs() && "setImplicitRef() out of range!");
SetMachineOperandVal(i + getNumOperands(),
- MachineOperand::MO_VirtualRegister,
- V, isDef, isDefAndUse);
- }
-
- //
- // Information about registers used in this instruction.
- //
- const std::set<int> &getRegsUsed() const {
- return regsUsed;
- }
- bool isRegUsed(int regNum) const {
- return regsUsed.find(regNum) != regsUsed.end();
- }
-
- // insertusedreg - Add a register to the Used registers set...
- void insertUsedReg(unsigned Reg) {
- regsUsed.insert((int) Reg);
+ MachineOperand::MO_VirtualRegister, V);
}
//
"Trying to add an operand to a machine instr that is already done!");
operands.push_back(MachineOperand(reg, MachineOperand::MO_MachineRegister,
isDef ? MOTy::Def : MOTy::Use));
- insertUsedReg(reg);
}
/// addMachineRegOperand - Add a virtual register operand to this MachineInstr
"Trying to add an operand to a machine instr that is already done!");
operands.push_back(MachineOperand(reg, MachineOperand::MO_MachineRegister,
UTy));
- insertUsedReg(reg);
}
/// addZeroExtImmOperand - Add a zero extended constant argument to the
/// simply replace() and then set new operands with Set.*Operand methods
/// below.
///
- void replace(int Opcode, unsigned numOperands);
+ void replace(short Opcode, unsigned numOperands);
/// setOpcode - Replace the opcode of the current instruction with a new one.
///
- void setOpcode(unsigned Op) { opCode = Op; }
+ void setOpcode(unsigned Op) { Opcode = Op; }
/// RemoveOperand - Erase an operand from an instruction, leaving it with one
/// fewer operand than it started with.
//
void SetMachineOperandVal (unsigned i,
MachineOperand::MachineOperandType operandType,
- Value* V,
- bool isDef=false,
- bool isDefAndUse=false);
+ Value* V);
void SetMachineOperandConst (unsigned i,
MachineOperand::MachineOperandType operandType,
int64_t intValue);
- void SetMachineOperandReg (unsigned i,
- int regNum,
- bool isDef=false);
+ void SetMachineOperandReg(unsigned i, int regNum);
unsigned substituteValue(const Value* oldVal, Value* newVal,
- bool defsOnly = true);
+ bool defsOnly, bool notDefsAndUses,
+ bool& someArgsWereIgnored);
void setOperandHi32(unsigned i) { operands[i].markHi32(); }
void setOperandLo32(unsigned i) { operands[i].markLo32(); }
inline VTy operator->() const { return operator*(); }
- inline bool isUseOnly() const { return MI->getOperand(i).opIsUse(); }
- inline bool isDefOnly() const { return MI->getOperand(i).opIsDefOnly(); }
- inline bool isDefAndUse() const { return MI->getOperand(i).opIsDefAndUse();}
+ inline bool isUse() const { return MI->getOperand(i).isUse(); }
+ inline bool isDef() const { return MI->getOperand(i).isDef(); }
inline _Self& operator++() { i++; skipToNextVal(); return *this; }
inline _Self operator++(int) { _Self tmp = *this; ++*this; return tmp; }
}
};
-
//===----------------------------------------------------------------------===//
// Debugging Support
std::ostream& operator<<(std::ostream &OS, const MachineOperand &MO);
void PrintMachineInstructions(const Function *F);
+} // End llvm namespace
+
#endif