namespace llvm {
+class MCAsmInfo;
class TargetRegisterClass;
+class TargetRegisterInfo;
class LiveVariables;
class CalleeSavedInfo;
class SDNode;
class SelectionDAG;
+class MachineMemOperand;
template<class T> class SmallVectorImpl;
DBG_LABEL = 2,
EH_LABEL = 3,
GC_LABEL = 4,
- DECLARE = 5,
+
+ /// KILL - This instruction is a noop that is used only to adjust the liveness
+ /// of registers. This can be useful when dealing with sub-registers.
+ KILL = 5,
+
+ /// EXTRACT_SUBREG - This instruction takes two operands: a register
+ /// that has subregisters, and a subregister index. It returns the
+ /// extracted subregister value. This is commonly used to implement
+ /// truncation operations on target architectures which support it.
EXTRACT_SUBREG = 6,
+
+ /// INSERT_SUBREG - This instruction takes three operands: a register
+ /// that has subregisters, a register providing an insert value, and a
+ /// subregister index. It returns the value of the first register with
+ /// the value of the second register inserted. The first register is
+ /// often defined by an IMPLICIT_DEF, as is commonly used to implement
+ /// anyext operations on target architectures which support it.
INSERT_SUBREG = 7,
+
+ /// IMPLICIT_DEF - This is the MachineInstr-level equivalent of undef.
IMPLICIT_DEF = 8,
- SUBREG_TO_REG = 9
+
+ /// SUBREG_TO_REG - This instruction is similar to INSERT_SUBREG except
+ /// that the first operand is an immediate integer constant. This constant
+ /// is often zero, as is commonly used to implement zext operations on
+ /// target architectures which support it, such as with x86-64 (with
+ /// zext from i32 to i64 via implicit zero-extension).
+ SUBREG_TO_REG = 9,
+
+ /// COPY_TO_REGCLASS - This instruction is a placeholder for a plain
+ /// register-to-register copy into a specific register class. This is only
+ /// used between instruction selection and MachineInstr creation, before
+ /// virtual registers have been created for all the instructions, and it's
+ /// only needed in cases where the register classes implied by the
+ /// instructions are insufficient. The actual MachineInstrs to perform
+ /// the copy are emitted with the TargetInstrInfo::copyRegToReg hook.
+ COPY_TO_REGCLASS = 10
};
unsigned getNumOpcodes() const { return NumOpcodes; }
/// isTriviallyReMaterializable - Return true if the instruction is trivially
/// rematerializable, meaning it has no side effects and requires no operands
/// that aren't always available.
- bool isTriviallyReMaterializable(const MachineInstr *MI) const {
- return MI->getDesc().isRematerializable() &&
- isReallyTriviallyReMaterializable(MI);
+ bool isTriviallyReMaterializable(const MachineInstr *MI,
+ AliasAnalysis *AA = 0) const {
+ return MI->getOpcode() == IMPLICIT_DEF ||
+ (MI->getDesc().isRematerializable() &&
+ (isReallyTriviallyReMaterializable(MI, AA) ||
+ isReallyTriviallyReMaterializableGeneric(MI, AA)));
}
protected:
/// isReallyTriviallyReMaterializable - For instructions with opcodes for
- /// which the M_REMATERIALIZABLE flag is set, this function tests whether the
- /// instruction itself is actually trivially rematerializable, considering
- /// its operands. This is used for targets that have instructions that are
- /// only trivially rematerializable for specific uses. This predicate must
- /// return false if the instruction has any side effects other than
- /// producing a value, or if it requres any address registers that are not
- /// always available.
- virtual bool isReallyTriviallyReMaterializable(const MachineInstr *MI) const {
- return true;
+ /// which the M_REMATERIALIZABLE flag is set, this hook lets the target
+ /// specify whether the instruction is actually trivially rematerializable,
+ /// taking into consideration its operands. This predicate must return false
+ /// if the instruction has any side effects other than producing a value, or
+ /// if it requres any address registers that are not always available.
+ virtual bool isReallyTriviallyReMaterializable(const MachineInstr *MI,
+ AliasAnalysis *AA) const {
+ return false;
}
+private:
+ /// isReallyTriviallyReMaterializableGeneric - For instructions with opcodes
+ /// for which the M_REMATERIALIZABLE flag is set and the target hook
+ /// isReallyTriviallyReMaterializable returns false, this function does
+ /// target-independent tests to determine if the instruction is really
+ /// trivially rematerializable.
+ bool isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI,
+ AliasAnalysis *AA) const;
+
public:
- /// Return true if the instruction is a register to register move
- /// and leave the source and dest operands in the passed parameters.
+ /// isMoveInstr - Return true if the instruction is a register to register
+ /// move and return the source and dest operands and their sub-register
+ /// indices by reference.
virtual bool isMoveInstr(const MachineInstr& MI,
- unsigned& sourceReg,
- unsigned& destReg) const {
+ unsigned& SrcReg, unsigned& DstReg,
+ unsigned& SrcSubIdx, unsigned& DstSubIdx) const {
+ return false;
+ }
+
+ /// isIdentityCopy - Return true if the instruction is a copy (or
+ /// extract_subreg, insert_subreg, subreg_to_reg) where the source and
+ /// destination registers are the same.
+ bool isIdentityCopy(const MachineInstr &MI) const {
+ unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
+ if (isMoveInstr(MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) &&
+ SrcReg == DstReg)
+ return true;
+
+ if (MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG &&
+ MI.getOperand(0).getReg() == MI.getOperand(1).getReg())
+ return true;
+
+ if ((MI.getOpcode() == TargetInstrInfo::INSERT_SUBREG ||
+ MI.getOpcode() == TargetInstrInfo::SUBREG_TO_REG) &&
+ MI.getOperand(0).getReg() == MI.getOperand(2).getReg())
+ return true;
return false;
}
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than loading from the stack slot.
- virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const{
+ virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const {
+ return 0;
+ }
+
+ /// isLoadFromStackSlotPostFE - Check for post-frame ptr elimination
+ /// stack locations as well. This uses a heuristic so it isn't
+ /// reliable for correctness.
+ virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI,
+ int &FrameIndex) const {
+ return 0;
+ }
+
+ /// hasLoadFromStackSlot - If the specified machine instruction has
+ /// a load from a stack slot, return true along with the FrameIndex
+ /// of the loaded stack slot and the machine mem operand containing
+ /// the reference. If not, return false. Unlike
+ /// isLoadFromStackSlot, this returns true for any instructions that
+ /// loads from the stack. This is just a hint, as some cases may be
+ /// missed.
+ virtual bool hasLoadFromStackSlot(const MachineInstr *MI,
+ const MachineMemOperand *&MMO,
+ int &FrameIndex) const {
return 0;
}
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
- virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const {
+ virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const {
+ return 0;
+ }
+
+ /// isStoreToStackSlotPostFE - Check for post-frame ptr elimination
+ /// stack locations as well. This uses a heuristic so it isn't
+ /// reliable for correctness.
+ virtual unsigned isStoreToStackSlotPostFE(const MachineInstr *MI,
+ int &FrameIndex) const {
+ return 0;
+ }
+
+ /// hasStoreToStackSlot - If the specified machine instruction has a
+ /// store to a stack slot, return true along with the FrameIndex of
+ /// the loaded stack slot and the machine mem operand containing the
+ /// reference. If not, return false. Unlike isStoreToStackSlot,
+ /// this returns true for any instructions that loads from the
+ /// stack. This is just a hint, as some cases may be missed.
+ virtual bool hasStoreToStackSlot(const MachineInstr *MI,
+ const MachineMemOperand *&MMO,
+ int &FrameIndex) const {
return 0;
}
/// specific location targeting a new destination register.
virtual void reMaterialize(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
- unsigned DestReg,
- const MachineInstr *Orig) const = 0;
-
- /// isInvariantLoad - Return true if the specified instruction (which is
- /// marked mayLoad) is loading from a location whose value is invariant across
- /// the function. For example, loading a value from the constant pool or from
- /// from the argument area of a function if it does not change. This should
- /// only return true of *all* loads the instruction does are invariant (if it
- /// does multiple loads).
- virtual bool isInvariantLoad(MachineInstr *MI) const {
- return false;
- }
-
+ unsigned DestReg, unsigned SubIdx,
+ const MachineInstr *Orig,
+ const TargetRegisterInfo *TRI) const = 0;
+
/// 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 one or more true
virtual MachineInstr *commuteInstruction(MachineInstr *MI,
bool NewMI = false) const = 0;
- /// CommuteChangesDestination - Return true if commuting the specified
- /// instruction will also changes the destination operand. Also return the
- /// current operand index of the would be new destination register by
- /// reference. This can happen when the commutable instruction is also a
- /// two-address instruction.
- virtual bool CommuteChangesDestination(MachineInstr *MI,
- unsigned &OpIdx) const = 0;
+ /// findCommutedOpIndices - If specified MI is commutable, return the two
+ /// operand indices that would swap value. Return true if the instruction
+ /// is not in a form which this routine understands.
+ virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
+ unsigned &SrcOpIdx2) const = 0;
+
+ /// isIdentical - Return true if two instructions are identical. This differs
+ /// from MachineInstr::isIdenticalTo() in that it does not require the
+ /// virtual destination registers to be the same. This is used by MachineLICM
+ /// and other MI passes to perform CSE.
+ virtual bool isIdentical(const MachineInstr *MI,
+ const MachineInstr *Other,
+ const MachineRegisterInfo *MRI) 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
/// 2. If this block ends with only an unconditional branch, it sets TBB to be
/// the destination block.
/// 3. If this block ends with an conditional branch and it falls through to
- /// an successor block, it sets TBB to be the branch destination block and a
- /// list of operands that evaluate the condition. These
- /// operands can be passed to other TargetInstrInfo methods to create new
- /// branches.
- /// 4. If this block ends with an conditional branch and an unconditional
- /// block, it returns the 'true' destination in TBB, the 'false' destination
- /// in FBB, and a list of operands that evaluate the condition. These
+ /// a successor block, it sets TBB to be the branch destination block and
+ /// a list of operands that evaluate the condition. These
/// operands can be passed to other TargetInstrInfo methods to create new
/// branches.
+ /// 4. If this block ends with a conditional branch followed by an
+ /// unconditional branch, it returns the 'true' destination in TBB, the
+ /// 'false' destination in FBB, and a list of operands that evaluate the
+ /// condition. These operands can be passed to other TargetInstrInfo
+ /// methods to create new branches.
///
/// Note that RemoveBranch and InsertBranch must be implemented to support
/// cases where this method returns success.
///
+ /// If AllowModify is true, then this routine is allowed to modify the basic
+ /// block (e.g. delete instructions after the unconditional branch).
+ ///
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
- SmallVectorImpl<MachineOperand> &Cond) const {
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify = false) const {
return true;
}
-
+
/// RemoveBranch - Remove the branching code at the end of the specific MBB.
/// This is only invoked in cases where AnalyzeBranch returns success. It
/// returns the number of instructions that were removed.
assert(0 && "Target didn't implement TargetInstrInfo::RemoveBranch!");
return 0;
}
-
- /// InsertBranch - Insert a branch into the end of the specified
- /// MachineBasicBlock. This operands to this method are the same as those
- /// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch
- /// returns success and when an unconditional branch (TBB is non-null, FBB is
- /// null, Cond is empty) needs to be inserted. It returns the number of
- /// instructions inserted.
+
+ /// InsertBranch - Insert branch code into the end of the specified
+ /// MachineBasicBlock. The operands to this method are the same as those
+ /// returned by AnalyzeBranch. This is only invoked in cases where
+ /// AnalyzeBranch returns success. It returns the number of instructions
+ /// inserted.
+ ///
+ /// It is also invoked by tail merging to add unconditional branches in
+ /// cases where AnalyzeBranch doesn't apply because there was no original
+ /// branch to analyze. At least this much must be implemented, else tail
+ /// merging needs to be disabled.
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
const SmallVectorImpl<MachineOperand> &Cond) const {
return false;
}
+ /// storeRegToStackSlot - Store the specified register of the given register
+ /// class to the specified stack frame index. The store instruction is to be
+ /// added to the given machine basic block before the specified machine
+ /// instruction. If isKill is true, the register operand is the last use and
+ /// must be marked kill.
virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned SrcReg, bool isKill, int FrameIndex,
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!");
- }
-
+ /// loadRegFromStackSlot - Load the specified register of the given register
+ /// class from the specified stack frame index. The load instruction is to be
+ /// added to the given machine basic block before the specified machine
+ /// instruction.
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
/// operand folded, otherwise NULL is returned. The client is responsible for
/// removing the old instruction and adding the new one in the instruction
/// stream.
- virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
- MachineInstr* MI,
- const SmallVectorImpl<unsigned> &Ops,
- int FrameIndex) const {
- return 0;
- }
+ MachineInstr* foldMemoryOperand(MachineFunction &MF,
+ MachineInstr* MI,
+ const SmallVectorImpl<unsigned> &Ops,
+ int FrameIndex) const;
/// foldMemoryOperand - Same as the previous version except it allows folding
/// of any load and store from / to any address, not just from a specific
/// stack slot.
- virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+ MachineInstr* foldMemoryOperand(MachineFunction &MF,
+ MachineInstr* MI,
+ const SmallVectorImpl<unsigned> &Ops,
+ MachineInstr* LoadMI) const;
+
+protected:
+ /// foldMemoryOperandImpl - Target-dependent implementation for
+ /// foldMemoryOperand. Target-independent code in foldMemoryOperand will
+ /// take care of adding a MachineMemOperand to the newly created instruction.
+ virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
MachineInstr* MI,
const SmallVectorImpl<unsigned> &Ops,
- MachineInstr* LoadMI) const {
+ int FrameIndex) const {
return 0;
}
- /// canFoldMemoryOperand - Returns true if the specified load / store is
+ /// foldMemoryOperandImpl - Target-dependent implementation for
+ /// foldMemoryOperand. Target-independent code in foldMemoryOperand will
+ /// take care of adding a MachineMemOperand to the newly created instruction.
+ virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
+ MachineInstr* MI,
+ const SmallVectorImpl<unsigned> &Ops,
+ MachineInstr* LoadMI) const {
+ return 0;
+ }
+
+public:
+ /// canFoldMemoryOperand - Returns true for the specified load / store if
/// folding is possible.
virtual
bool canFoldMemoryOperand(const MachineInstr *MI,
/// possible, returns true as well as the new instructions by reference.
virtual bool unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI,
unsigned Reg, bool UnfoldLoad, bool UnfoldStore,
- SmallVectorImpl<MachineInstr*> &NewMIs) const{
+ SmallVectorImpl<MachineInstr*> &NewMIs) const{
return false;
}
/// getOpcodeAfterMemoryUnfold - Returns the opcode of the would be new
/// instruction after load / store are unfolded from an instruction of the
/// specified opcode. It returns zero if the specified unfolding is not
- /// possible.
+ /// possible. If LoadRegIndex is non-null, it is filled in with the operand
+ /// index of the operand which will hold the register holding the loaded
+ /// value.
virtual unsigned getOpcodeAfterMemoryUnfold(unsigned Opc,
- bool UnfoldLoad, bool UnfoldStore) const {
+ bool UnfoldLoad, bool UnfoldStore,
+ unsigned *LoadRegIndex = 0) const {
return 0;
}
- /// 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
- /// indirect branches (jump tables).
- virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
- return false;
- }
-
/// ReverseBranchCondition - Reverses the branch condition of the specified
/// condition list, returning false on success and true if it cannot be
/// reversed.
/// insertNoop - Insert a noop into the instruction stream at the specified
/// point.
virtual void insertNoop(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI) const {
- assert(0 && "Target didn't implement insertNoop!");
- abort();
- }
-
+ MachineBasicBlock::iterator MI) const;
+
/// isPredicated - Returns true if the instruction is already predicated.
///
virtual bool isPredicated(const MachineInstr *MI) const {
return false;
}
- /// getPointerRegClass - Returns a TargetRegisterClass used for pointer
- /// values.
- virtual const TargetRegisterClass *getPointerRegClass() const {
- assert(0 && "Target didn't implement getPointerRegClass!");
- abort();
- return 0; // Must return a value in order to compile with VS 2005
+ /// isPredicable - Return true if the specified instruction can be predicated.
+ /// By default, this returns true for every instruction with a
+ /// PredicateOperand.
+ virtual bool isPredicable(MachineInstr *MI) const {
+ return MI->getDesc().isPredicable();
+ }
+
+ /// isSafeToMoveRegClassDefs - Return true if it's safe to move a machine
+ /// instruction that defines the specified register class.
+ virtual bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const {
+ return true;
}
/// GetInstSize - Returns the size of the specified Instruction.
return 0;
}
- /// GetFunctionSizeInBytes - Returns the size of the specified MachineFunction.
+ /// GetFunctionSizeInBytes - Returns the size of the specified
+ /// MachineFunction.
///
virtual unsigned GetFunctionSizeInBytes(const MachineFunction &MF) const = 0;
-
+
+ /// Measure the specified inline asm to determine an approximation of its
+ /// length.
+ virtual unsigned getInlineAsmLength(const char *Str,
+ const MCAsmInfo &MAI) const;
};
/// TargetInstrInfoImpl - This is the default implementation of
public:
virtual MachineInstr *commuteInstruction(MachineInstr *MI,
bool NewMI = false) const;
- virtual bool CommuteChangesDestination(MachineInstr *MI,
- unsigned &OpIdx) const;
+ virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
+ unsigned &SrcOpIdx2) const;
virtual bool PredicateInstruction(MachineInstr *MI,
const SmallVectorImpl<MachineOperand> &Pred) const;
virtual void reMaterialize(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
- unsigned DestReg,
- const MachineInstr *Orig) const;
+ unsigned DestReg, unsigned SubReg,
+ const MachineInstr *Orig,
+ const TargetRegisterInfo *TRI) const;
+ virtual bool isIdentical(const MachineInstr *MI,
+ const MachineInstr *Other,
+ const MachineRegisterInfo *MRI) const;
+
virtual unsigned GetFunctionSizeInBytes(const MachineFunction &MF) const;
};