Fix a case where we incorrectly returned hasComputableLoopEvolution for
[oota-llvm.git] / include / llvm / Target / TargetInstrInfo.h
index fe4922a5ab08e398d7bf6754e6e7d89f29ae7738..d5237f2f7cc277617211f7fc319d0ad49edc9728 100644 (file)
@@ -48,20 +48,32 @@ const unsigned M_BRANCH_FLAG                = 1 << 1;
 const unsigned M_CALL_FLAG             = 1 << 2;
 const unsigned M_RET_FLAG              = 1 << 3;
 const unsigned M_BARRIER_FLAG           = 1 << 4;
-const unsigned M_DELAY_SLOT             = 1 << 5;
+const unsigned M_DELAY_SLOT_FLAG        = 1 << 5;
 const unsigned M_CC_FLAG               = 1 << 6;
-const unsigned M_LOAD_FLAG             = 1 << 10;
-const unsigned M_STORE_FLAG            = 1 << 12;
-// 3-addr instructions which really work like 2-addr ones, eg. X86 add/sub
-const unsigned M_2_ADDR_FLAG           = 1 << 15;
+const unsigned M_LOAD_FLAG             = 1 << 7;
+const unsigned M_STORE_FLAG            = 1 << 8;
+
+// M_2_ADDR_FLAG - 3-addr instructions which really work like 2-addr ones.
+const unsigned M_2_ADDR_FLAG            = 1 << 9;
+
+// M_CONVERTIBLE_TO_3_ADDR - This is a M_2_ADDR_FLAG instruction which can be
+// changed into a 3-address instruction if the first two operands cannot be
+// assigned to the same register.  The target must implement the
+// TargetInstrInfo::convertToThreeAddress method for this instruction.
+const unsigned M_CONVERTIBLE_TO_3_ADDR = 1 << 10;
+
+// This M_COMMUTABLE - is a 2- or 3-address instruction (of the form X = op Y,
+// Z), which produces the same result if Y and Z are exchanged.
+const unsigned M_COMMUTABLE            = 1 << 11;
 
 // M_TERMINATOR_FLAG - Is this instruction part of the terminator for a basic
 // block?  Typically this is things like return and branch instructions.
 // Various passes use this to insert code into the bottom of a basic block, but
 // before control flow occurs.
-const unsigned M_TERMINATOR_FLAG       = 1 << 16;
+const unsigned M_TERMINATOR_FLAG       = 1 << 12;
 
-struct TargetInstrDescriptor {
+class TargetInstrDescriptor {
+public:
   const char *    Name;          // Assembly language mnemonic for the opcode.
   int             numOperands;   // Number of args; -1 if variable #args
   int             resultPos;     // Position of the result; -1 if no result
@@ -151,6 +163,32 @@ public:
     return false;
   }
 
+  /// convertToThreeAddress - This method must be implemented by targets that
+  /// set the M_CONVERTIBLE_TO_3_ADDR flag.  When this flag is set, the target
+  /// may be able to convert a two-address instruction into a true
+  /// three-address instruction on demand.  This allows the X86 target (for
+  /// example) to convert ADD and SHL instructions into LEA instructions if they
+  /// would require register copies due to two-addressness.
+  ///
+  /// This method returns a null pointer if the transformation cannot be
+  /// performed, otherwise it returns the new instruction.
+  ///
+  virtual MachineInstr *convertToThreeAddress(MachineInstr *TA) const {
+    return 0;
+  }
+
+  /// commuteInstruction - If a target has any instructions that are commutable,
+  /// but require converting to a different instruction or making non-trivial
+  /// changes to commute them, this method can overloaded to do this.  The
+  /// default implementation of this method simply swaps the first two operands
+  /// of MI and returns it.
+  ///
+  /// If a target wants to make more aggressive changes, they can construct and
+  /// return a new machine instruction.  If an instruction cannot commute, it
+  /// can also return null.
+  ///
+  virtual MachineInstr *commuteInstruction(MachineInstr *MI) const;
+
   /// Insert a goto (unconditional branch) sequence to TMBB, at the
   /// end of MBB
   virtual void insertGoto(MachineBasicBlock& MBB,
@@ -208,7 +246,7 @@ public:
   /// hasDelaySlot - Returns true if the specified instruction has a delay slot
   /// which must be filled by the code generator.
   bool hasDelaySlot(unsigned Opcode) const {
-    return get(Opcode).Flags & M_DELAY_SLOT;
+    return get(Opcode).Flags & M_DELAY_SLOT_FLAG;
   }
 
   virtual bool hasResultInterlock(MachineOpCode Opcode) const {