eliminate some extraneous methods in SDNode
[oota-llvm.git] / include / llvm / CodeGen / MachineInstr.h
index 443956e401d2d0c7f149f21ced54afb09a181082..ad2ccdf8ca14adc40ef72e4018707d69b78b6862 100644 (file)
 
 #include "llvm/ADT/iterator"
 #include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Streams.h"
 #include <vector>
 #include <cassert>
+#include <iosfwd>
 
 namespace llvm {
 
 class Value;
 class Function;
 class MachineBasicBlock;
+class TargetInstrDescriptor;
 class TargetMachine;
 class GlobalValue;
 
@@ -38,26 +41,6 @@ template <typename T> struct ilist;
 //   Representation of each machine instruction operand.
 //
 struct MachineOperand {
-private:
-  // Bit fields of the flags variable used for different operand properties
-  enum {
-    DEFFLAG     = 0x01,       // this is a def of the operand
-    USEFLAG     = 0x02        // this is a use of the operand
-  };
-
-public:
-  // UseType - This enum describes how the machine operand is used by
-  // the instruction. Note that the MachineInstr/Operator class
-  // currently uses bool arguments to represent this information
-  // instead of an enum.  Eventually this should change over to use
-  // this _easier to read_ representation instead.
-  //
-  enum UseType {
-    Use = USEFLAG,        /// only read
-    Def = DEFFLAG,        /// only written
-    UseAndDef = Use | Def /// read AND written
-  };
-
   enum MachineOperandType {
     MO_Register,                // Register operand.
     MO_Immediate,               // Immediate Operand
@@ -78,24 +61,50 @@ private:
     int64_t immedVal;         // For MO_Immediate and MO_*Index.
   } contents;
 
-  char flags;                   // see bit field definitions above
-  MachineOperandType opType:8;  // Pack into 8 bits efficiently after flags.
+  MachineOperandType opType:8; // Discriminate the union.
+  bool IsDef : 1;              // True if this is a def, false if this is a use.
+  bool IsImp : 1;              // True if this is an implicit def or use.
+
+  bool IsKill : 1;             // True if this is a reg use and the reg is dead
+                               // immediately after the read.
+  bool IsDead : 1;             // True if this is a reg def and the reg is dead
+                               // immediately after the write. i.e. A register
+                               // that is defined but never used.
   
   /// offset - Offset to address of global or external, only valid for
   /// MO_GlobalAddress, MO_ExternalSym and MO_ConstantPoolIndex
   int offset;
 
   MachineOperand() {}
+
+  void print(std::ostream &os) const;
+  void print(std::ostream *os) const { if (os) print(*os); }
+
 public:
   MachineOperand(const MachineOperand &M) {
     *this = M;
   }
-
+  
   ~MachineOperand() {}
-
+  
+  static MachineOperand CreateImm(int64_t Val) {
+    MachineOperand Op;
+    Op.opType = MachineOperand::MO_Immediate;
+    Op.contents.immedVal = Val;
+    Op.IsDef = false;
+    Op.IsImp = false;
+    Op.IsKill = false;
+    Op.IsDead = false;
+    Op.offset = 0;
+    return Op;
+  }
+  
   const MachineOperand &operator=(const MachineOperand &MO) {
     contents = MO.contents;
-    flags    = MO.flags;
+    IsDef    = MO.IsDef;
+    IsImp    = MO.IsImp;
+    IsKill   = MO.IsKill;
+    IsDead   = MO.IsDead;
     opType   = MO.opType;
     offset   = MO.offset;
     return *this;
@@ -105,10 +114,6 @@ public:
   ///
   MachineOperandType getType() const { return opType; }
 
-  /// getUseType - Returns the MachineOperandUseType of this operand.
-  ///
-  UseType getUseType() const { return UseType(flags & (USEFLAG|DEFFLAG)); }
-
   /// Accessors that tell you what kind of MachineOperand you're looking at.
   ///
   bool isReg() const { return opType == MO_Register; }
@@ -124,10 +129,19 @@ public:
   bool isGlobalAddress() const { return opType == MO_GlobalAddress; }
   bool isExternalSymbol() const { return opType == MO_ExternalSymbol; }
 
+  int64_t getImm() const {
+    assert(isImm() && "Wrong MachineOperand accessor");
+    return contents.immedVal;
+  }
+  
   int64_t getImmedValue() const {
-    assert(isImmediate() && "Wrong MachineOperand accessor");
+    assert(isImm() && "Wrong MachineOperand accessor");
     return contents.immedVal;
   }
+  MachineBasicBlock *getMBB() const {
+    assert(isMachineBasicBlock() && "Wrong MachineOperand accessor");
+    return contents.MBB;
+  }
   MachineBasicBlock *getMachineBasicBlock() const {
     assert(isMachineBasicBlock() && "Wrong MachineOperand accessor");
     return contents.MBB;
@@ -162,13 +176,56 @@ public:
     return contents.SymbolName;
   }
 
-  /// MachineOperand methods for testing that work on any kind of
-  /// MachineOperand...
-  ///
-  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 isUse() const { 
+    assert(isRegister() && "Wrong MachineOperand accessor");
+    return !IsDef;
+  }
+  bool isDef() const {
+    assert(isRegister() && "Wrong MachineOperand accessor");
+    return IsDef;
+  }
+  void setIsUse() {
+    assert(isRegister() && "Wrong MachineOperand accessor");
+    IsDef = false;
+  }
+  void setIsDef() {
+    assert(isRegister() && "Wrong MachineOperand accessor");
+    IsDef = true;
+  }
+
+  bool isImplicit() const { 
+    assert(isRegister() && "Wrong MachineOperand accessor");
+    return IsImp;
+  }
+  void setImplicit() { 
+    assert(isRegister() && "Wrong MachineOperand accessor");
+    IsImp = true;
+  }
+
+  bool isKill() const {
+    assert(isRegister() && "Wrong MachineOperand accessor");
+    return IsKill;
+  }
+  bool isDead() const {
+    assert(isRegister() && "Wrong MachineOperand accessor");
+    return IsDead;
+  }
+  void setIsKill() {
+    assert(isRegister() && !IsDef && "Wrong MachineOperand accessor");
+    IsKill = true;
+  }
+  void setIsDead() {
+    assert(isRegister() && IsDef && "Wrong MachineOperand accessor");
+    IsDead = true;
+  }
+  void unsetIsKill() {
+    assert(isRegister() && !IsDef && "Wrong MachineOperand accessor");
+    IsKill = false;
+  }
+  void unsetIsDead() {
+    assert(isRegister() && IsDef && "Wrong MachineOperand accessor");
+    IsDead = false;
+  }
 
   /// getReg - Returns the register number.
   ///
@@ -185,7 +242,11 @@ public:
   }
 
   void setImmedValue(int64_t immVal) {
-    assert(isImmediate() && "Wrong MachineOperand mutator");
+    assert(isImm() && "Wrong MachineOperand mutator");
+    contents.immedVal = immVal;
+  }
+  void setImm(int64_t immVal) {
+    assert(isImm() && "Wrong MachineOperand mutator");
     contents.immedVal = immVal;
   }
 
@@ -195,6 +256,18 @@ public:
         "Wrong MachineOperand accessor");
     offset = Offset;
   }
+  void setConstantPoolIndex(unsigned Idx) {
+    assert(isConstantPoolIndex() && "Wrong MachineOperand accessor");
+    contents.immedVal = Idx;
+  }
+  void setJumpTableIndex(unsigned Idx) {
+    assert(isJumpTableIndex() && "Wrong MachineOperand accessor");
+    contents.immedVal = Idx;
+  }
+  
+  /// isIdenticalTo - Return true if this operand is identical to the specified
+  /// operand. Note: This method ignores isKill and isDead properties.
+  bool isIdenticalTo(const MachineOperand &Other) const;
   
   /// ChangeToImmediate - Replace this operand with a new immediate operand of
   /// the specified value.  If an operand is known to be an immediate already,
@@ -207,12 +280,19 @@ public:
   /// ChangeToRegister - Replace this operand with a new register operand of
   /// the specified value.  If an operand is known to be an register already,
   /// the setReg method should be used.
-  void ChangeToRegister(unsigned Reg) {
+  void ChangeToRegister(unsigned Reg, bool isDef) {
     opType = MO_Register;
     contents.RegNo = Reg;
+    IsDef = isDef;
+    IsImp = false;
+    IsKill = false;
+    IsDead = false;
   }
 
-  friend std::ostream& operator<<(std::ostream& os, const MachineOperand& mop);
+  friend std::ostream& operator<<(std::ostream& os, const MachineOperand& mop) {
+    mop.print(os);
+    return os;
+  }
 
   friend class MachineInstr;
 };
@@ -222,7 +302,10 @@ public:
 /// MachineInstr - Representation of each machine instruction.
 ///
 class MachineInstr {
-  short Opcode;                         // the opcode
+  const TargetInstrDescriptor *TID;     // Instruction descriptor.
+  unsigned short NumImplicitOps;        // Number of implicit operands (which
+                                        // are determined at construction time).
+
   std::vector<MachineOperand> Operands; // the operands
   MachineInstr* prev, *next;            // links for our intrusive list
   MachineBasicBlock* parent;            // pointer to the owning basic block
@@ -238,24 +321,33 @@ class MachineInstr {
   friend struct ilist_traits<MachineInstr>;
 
 public:
-  /// MachineInstr ctor - This constructor reserve's space for numOperand
-  /// operands.
-  MachineInstr(short Opcode, unsigned numOperands);
+  /// MachineInstr ctor - This constructor creates a dummy MachineInstr with
+  /// TID NULL and no operands.
+  MachineInstr();
+
+  /// MachineInstr ctor - This constructor create a MachineInstr and add the
+  /// implicit operands. It reserves space for number of operands specified by
+  /// TargetInstrDescriptor.
+  MachineInstr(const TargetInstrDescriptor &TID);
 
   /// 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, short Opcode, unsigned numOps);
+  MachineInstr(MachineBasicBlock *MBB, const TargetInstrDescriptor &TID);
 
   ~MachineInstr();
 
   const MachineBasicBlock* getParent() const { return parent; }
   MachineBasicBlock* getParent() { return parent; }
+  
+  /// getInstrDescriptor - Returns the target instruction descriptor of this
+  /// MachineInstr.
+  const TargetInstrDescriptor *getInstrDescriptor() const { return TID; }
 
   /// getOpcode - Returns the opcode of this MachineInstr.
   ///
-  const int getOpcode() const { return Opcode; }
+  const int getOpcode() const;
 
   /// Access to explicit operands of the instruction.
   ///
@@ -270,6 +362,18 @@ public:
     return Operands[i];
   }
 
+  
+  /// isIdenticalTo - Return true if this instruction is identical to (same
+  /// opcode and same operands as) the specified instruction.
+  bool isIdenticalTo(const MachineInstr *Other) const {
+    if (Other->getOpcode() != getOpcode() ||
+        Other->getNumOperands() != getNumOperands())
+      return false;
+    for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
+      if (!getOperand(i).isIdenticalTo(Other->getOperand(i)))
+        return false;
+    return true;
+  }
 
   /// clone - Create a copy of 'this' instruction that is identical in
   /// all ways except the the instruction has no parent, prev, or next.
@@ -285,12 +389,28 @@ public:
     delete removeFromParent();
   }
 
+  /// findRegisterUseOperand() - Returns the MachineOperand that is a use of
+  /// the specific register or NULL if it is not found.
+  MachineOperand *findRegisterUseOperand(unsigned Reg);
+  
+  /// copyKillDeadInfo - Copies kill / dead operand properties from MI.
+  ///
+  void copyKillDeadInfo(const MachineInstr *MI);
+
   //
   // Debugging support
   //
+  void print(std::ostream *OS, const TargetMachine *TM) const {
+    if (OS) print(*OS, TM);
+  }
   void print(std::ostream &OS, const TargetMachine *TM) const;
+  void print(std::ostream &OS) const;
+  void print(std::ostream *OS) const { if (OS) print(*OS); }
   void dump() const;
-  friend std::ostream& operator<<(std::ostream& os, const MachineInstr& minstr);
+  friend std::ostream& operator<<(std::ostream& os, const MachineInstr& minstr){
+    minstr.print(os);
+    return os;
+  }
 
   //===--------------------------------------------------------------------===//
   // Accessors to add operands when building up machine instructions.
@@ -298,11 +418,14 @@ public:
 
   /// addRegOperand - Add a register operand.
   ///
-  void addRegOperand(unsigned Reg,
-                     MachineOperand::UseType UTy = MachineOperand::Use) {
-    MachineOperand &Op = AddNewOperand();
+  void addRegOperand(unsigned Reg, bool IsDef, bool IsImp = false,
+                     bool IsKill = false, bool IsDead = false) {
+    MachineOperand &Op = AddNewOperand(IsImp);
     Op.opType = MachineOperand::MO_Register;
-    Op.flags = UTy;
+    Op.IsDef = IsDef;
+    Op.IsImp = IsImp;
+    Op.IsKill = IsKill;
+    Op.IsDead = IsDead;
     Op.contents.RegNo = Reg;
     Op.offset = 0;
   }
@@ -313,7 +436,6 @@ public:
   void addImmOperand(int64_t Val) {
     MachineOperand &Op = AddNewOperand();
     Op.opType = MachineOperand::MO_Immediate;
-    Op.flags = 0;
     Op.contents.immedVal = Val;
     Op.offset = 0;
   }
@@ -321,7 +443,6 @@ public:
   void addMachineBasicBlockOperand(MachineBasicBlock *MBB) {
     MachineOperand &Op = AddNewOperand();
     Op.opType = MachineOperand::MO_MachineBasicBlock;
-    Op.flags = 0;
     Op.contents.MBB = MBB;
     Op.offset = 0;
   }
@@ -331,7 +452,6 @@ public:
   void addFrameIndexOperand(unsigned Idx) {
     MachineOperand &Op = AddNewOperand();
     Op.opType = MachineOperand::MO_FrameIndex;
-    Op.flags = 0;
     Op.contents.immedVal = Idx;
     Op.offset = 0;
   }
@@ -342,7 +462,6 @@ public:
   void addConstantPoolIndexOperand(unsigned Idx, int Offset) {
     MachineOperand &Op = AddNewOperand();
     Op.opType = MachineOperand::MO_ConstantPoolIndex;
-    Op.flags = 0;
     Op.contents.immedVal = Idx;
     Op.offset = Offset;
   }
@@ -353,7 +472,6 @@ public:
   void addJumpTableIndexOperand(unsigned Idx) {
     MachineOperand &Op = AddNewOperand();
     Op.opType = MachineOperand::MO_JumpTableIndex;
-    Op.flags = 0;
     Op.contents.immedVal = Idx;
     Op.offset = 0;
   }
@@ -361,7 +479,6 @@ public:
   void addGlobalAddressOperand(GlobalValue *GV, int Offset) {
     MachineOperand &Op = AddNewOperand();
     Op.opType = MachineOperand::MO_GlobalAddress;
-    Op.flags = 0;
     Op.contents.GV = GV;
     Op.offset = Offset;
   }
@@ -371,7 +488,6 @@ public:
   void addExternalSymbolOperand(const char *SymName) {
     MachineOperand &Op = AddNewOperand();
     Op.opType = MachineOperand::MO_ExternalSymbol;
-    Op.flags = 0;
     Op.contents.SymbolName = SymName;
     Op.offset = 0;
   }
@@ -380,9 +496,10 @@ public:
   // Accessors used to modify instructions in place.
   //
 
-  /// setOpcode - Replace the opcode of the current instruction with a new one.
+  /// setInstrDescriptor - Replace the instruction descriptor (thus opcode) of
+  /// the current instruction with a new one.
   ///
-  void setOpcode(unsigned Op) { Opcode = Op; }
+  void setInstrDescriptor(const TargetInstrDescriptor &tid) { TID = &tid; }
 
   /// RemoveOperand - Erase an operand  from an instruction, leaving it with one
   /// fewer operand than it started with.
@@ -391,12 +508,21 @@ public:
     Operands.erase(Operands.begin()+i);
   }
 private:
-  MachineOperand &AddNewOperand() {
-    assert(!OperandsComplete() &&
+  MachineOperand &AddNewOperand(bool IsImp = false) {
+    assert((IsImp || !OperandsComplete()) &&
            "Trying to add an operand to a machine instr that is already done!");
-    Operands.push_back(MachineOperand());
-    return Operands.back();
+    if (NumImplicitOps == 0) { // This is true most of the time.
+      Operands.push_back(MachineOperand());
+      return Operands.back();
+    } else {
+      return *Operands.insert(Operands.begin()+Operands.size()-NumImplicitOps,
+                              MachineOperand());
+    }
   }
+
+  /// addImplicitDefUseOperands - Add all implicit def and use operands to
+  /// this instruction.
+  void addImplicitDefUseOperands();
 };
 
 //===----------------------------------------------------------------------===//