describe isStore and simplify the implementation of hasUnmodelledSideEffects.
[oota-llvm.git] / include / llvm / Target / TargetInstrInfo.h
index e617e691ef683dc5512ef7b33cb176ec29e79736..7b192700c6abf39dc3e62a75a4604744da40bef5 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     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 is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -26,6 +26,9 @@ class MachineInstr;
 class TargetMachine;
 class TargetRegisterClass;
 class LiveVariables;
+class CalleeSavedInfo;
+
+template<class T> class SmallVectorImpl;
 
 //---------------------------------------------------------------------------
 // Data types used to define information about a single machine instruction
@@ -46,7 +49,13 @@ const unsigned M_RET_FLAG              = 1 << 2;
 const unsigned M_BARRIER_FLAG          = 1 << 3;
 const unsigned M_DELAY_SLOT_FLAG       = 1 << 4;
 const unsigned M_LOAD_FLAG             = 1 << 5;
+  
+/// M_STORE_FLAG - This flag is set to any instruction that could possibly
+/// modify memory.  Instructions with this flag set are not necessarily simple
+/// store instructions, they may store a modified value based on their operands,
+/// or may not actually modify anything, for example.
 const unsigned M_STORE_FLAG            = 1 << 6;
+  
 const unsigned M_INDIRECT_FLAG         = 1 << 7;
 const unsigned M_IMPLICIT_DEF_FLAG     = 1 << 8;
 
@@ -91,17 +100,23 @@ const unsigned M_NOT_DUPLICABLE        = 1 << 16;
 // ARM instructions which can set condition code if 's' bit is set.
 const unsigned M_HAS_OPTIONAL_DEF      = 1 << 17;
 
-// M_MAY_HAVE_SIDE_EFFECTS - Set if this instruction *might* have side effects,
-// e.g. load instructions. Note: This and M_NEVER_HAS_SIDE_EFFECTS are mutually
-// exclusive. You can't set both! If neither flag is set, then the instruction
-// *always* has side effects.
-const unsigned M_MAY_HAVE_SIDE_EFFECTS = 1 << 18;
-
-// M_NEVER_HAS_SIDE_EFFECTS - Set if this instruction *never* has side effects,
-// e.g., xor on X86.  Note: This and M_MAY_HAVE_SIDE_EFFECTS are mutually
-// exclusive. You can't set both! If neither flag is set, then the instruction
-// *always* has side effects.
-const unsigned M_NEVER_HAS_SIDE_EFFECTS = 1 << 19;
+// M_NEVER_HAS_SIDE_EFFECTS - Set if this instruction has no side effects that
+// are not captured by any operands of the instruction or other flags, and when
+// *all* instances of the instruction of that opcode have no side effects.
+//
+// Note: This and M_MAY_HAVE_SIDE_EFFECTS are mutually exclusive. You can't set
+// both! If neither flag is set, then the instruction *always* has side effects.
+const unsigned M_NEVER_HAS_SIDE_EFFECTS = 1 << 18;
+
+// M_MAY_HAVE_SIDE_EFFECTS - Set if some instances of this instruction can have
+// side effects. The virtual method "isReallySideEffectFree" is called to
+// determine this. Load instructions are an example of where this is useful. In
+// general, loads always have side effects. However, loads from constant pools
+// don't. We let the specific back end make this determination.
+//
+// Note: This and M_NEVER_HAS_SIDE_EFFECTS are mutually exclusive. You can't set
+// both! If neither flag is set, then the instruction *always* has side effects.
+const unsigned M_MAY_HAVE_SIDE_EFFECTS = 1 << 19;
 
 // Machine operand flags
 // M_LOOK_UP_PTR_REG_CLASS - Set if this operand is a pointer value and it
@@ -267,6 +282,11 @@ public:
   bool isLoad(MachineOpCode Opcode) const {
     return get(Opcode).Flags & M_LOAD_FLAG;
   }
+
+  /// isStore - Return true if this instruction could possibly modify memory.
+  /// Instructions with this flag set are not necessarily simple store
+  /// instructions, they may store a modified value based on their operands, or
+  /// may not actually modify anything, for example.
   bool isStore(MachineOpCode Opcode) const {
     return get(Opcode).Flags & M_STORE_FLAG;
   }
@@ -308,6 +328,15 @@ public:
            isReallyTriviallyReMaterializable(MI);
   }
 
+  /// hasUnmodelledSideEffects - Returns true if the instruction has side
+  /// effects that are not captured by any operands of the instruction or other
+  /// flags.
+  bool hasUnmodelledSideEffects(MachineInstr *MI) const {
+    const TargetInstrDescriptor *TID = MI->getInstrDescriptor();
+    if (TID->Flags & M_NEVER_HAS_SIDE_EFFECTS) return false;
+    if (!(TID->Flags & M_MAY_HAVE_SIDE_EFFECTS)) return true;
+    return !isReallySideEffectFree(MI); // May have side effects
+  }
 protected:
   /// isReallyTriviallyReMaterializable - For instructions with opcodes for
   /// which the M_REMATERIALIZABLE flag is set, this function tests whether the
@@ -321,6 +350,15 @@ protected:
     return true;
   }
 
+  /// isReallySideEffectFree - If the M_MAY_HAVE_SIDE_EFFECTS flag is set, this
+  /// method is called to determine if the specific instance of this
+  /// instruction has side effects. This is useful in cases of instructions,
+  /// like loads, which generally always have side effects. A load from a
+  /// constant pool doesn't have side effects, though. So we need to
+  /// differentiate it from the general case.
+  virtual bool isReallySideEffectFree(MachineInstr *MI) const {
+    return false;
+  }
 public:
   /// getOperandConstraint - Returns the value of the specific constraint if
   /// it is set. Returns -1 if it is not set.
@@ -381,7 +419,7 @@ public:
   /// return a new machine instruction.  If an instruction cannot commute, it
   /// can also return null.
   ///
-  virtual MachineInstr *commuteInstruction(MachineInstr *MI) const;
+  virtual MachineInstr *commuteInstruction(MachineInstr *MI) const = 0;
 
   /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
   /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
@@ -433,6 +471,63 @@ public:
     return 0;
   }
   
+  /// copyRegToReg - Add a copy between a pair of registers
+  virtual void copyRegToReg(MachineBasicBlock &MBB,
+                            MachineBasicBlock::iterator MI,
+                            unsigned DestReg, unsigned SrcReg,
+                            const TargetRegisterClass *DestRC,
+                            const TargetRegisterClass *SrcRC) const {
+    assert(0 && "Target didn't implement TargetInstrInfo::copyRegToReg!");
+  }
+  
+  virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
+                                   MachineBasicBlock::iterator MI,
+                                   unsigned SrcReg, bool isKill, int FrameIndex,
+                                   const TargetRegisterClass *RC) const {
+    assert(0 && "Target didn't implement TargetInstrInfo::storeRegToStackSlot!");
+  }
+
+  virtual void storeRegToAddr(MachineFunction &MF, unsigned SrcReg, bool isKill,
+                              SmallVectorImpl<MachineOperand> &Addr,
+                              const TargetRegisterClass *RC,
+                              SmallVectorImpl<MachineInstr*> &NewMIs) const {
+    assert(0 && "Target didn't implement TargetInstrInfo::storeRegToAddr!");
+  }
+
+  virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
+                                    MachineBasicBlock::iterator MI,
+                                    unsigned DestReg, int FrameIndex,
+                                    const TargetRegisterClass *RC) const {
+    assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromStackSlot!");
+  }
+
+  virtual void loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
+                               SmallVectorImpl<MachineOperand> &Addr,
+                               const TargetRegisterClass *RC,
+                               SmallVectorImpl<MachineInstr*> &NewMIs) const {
+    assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromAddr!");
+  }
+  
+  /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee
+  /// saved registers and returns true if it isn't possible / profitable to do
+  /// so by issuing a series of store instructions via
+  /// storeRegToStackSlot(). Returns false otherwise.
+  virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
+                                         MachineBasicBlock::iterator MI,
+                                const std::vector<CalleeSavedInfo> &CSI) const {
+    return false;
+  }
+
+  /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee
+  /// saved registers and returns true if it isn't possible / profitable to do
+  /// so by issuing a series of load instructions via loadRegToStackSlot().
+  /// Returns false otherwise.
+  virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
+                                           MachineBasicBlock::iterator MI,
+                                const std::vector<CalleeSavedInfo> &CSI) const {
+    return false;
+  }
+  
   /// BlockHasNoFallThrough - Return true if the specified block does not
   /// fall-through into its successor block.  This is primarily used when a
   /// branch is unanalyzable.  It is useful for things like unconditional
@@ -470,7 +565,7 @@ public:
   /// instruction. It returns true if the operation was successful.
   virtual
   bool PredicateInstruction(MachineInstr *MI,
-                            const std::vector<MachineOperand> &Pred) const;
+                            const std::vector<MachineOperand> &Pred) const = 0;
 
   /// SubsumesPredicate - Returns true if the first specified predicate
   /// subsumes the second, e.g. GE subsumes GT.
@@ -497,6 +592,21 @@ public:
   }
 };
 
+/// TargetInstrInfoImpl - This is the default implementation of
+/// TargetInstrInfo, which just provides a couple of default implementations
+/// for various methods.  This separated out because it is implemented in
+/// libcodegen, not in libtarget.
+class TargetInstrInfoImpl : public TargetInstrInfo {
+protected:
+  TargetInstrInfoImpl(const TargetInstrDescriptor *desc, unsigned NumOpcodes)
+  : TargetInstrInfo(desc, NumOpcodes) {}
+public:
+  virtual MachineInstr *commuteInstruction(MachineInstr *MI) const;
+  virtual bool PredicateInstruction(MachineInstr *MI,
+                              const std::vector<MachineOperand> &Pred) const;
+  
+};
+
 } // End llvm namespace
 
 #endif