X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FTarget%2FTargetInstrInfo.h;h=d95e4e8acdef2e13508587364b9215cc6536f2f8;hb=518bb53485df640d7b7e3f6b0544099020c42aa7;hp=9a96eb5b381f35d77ee0bdb53eb1eceb4b26c8ab;hpb=641055225092833197efe8e5bce01d50bcf1daae;p=oota-llvm.git diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 9a96eb5b381..d95e4e8acde 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -7,358 +7,125 @@ // //===----------------------------------------------------------------------===// // -// This file describes the target machine instructions to the code generator. +// This file describes the target machine instruction set to the code generator. // //===----------------------------------------------------------------------===// #ifndef LLVM_TARGET_TARGETINSTRINFO_H #define LLVM_TARGET_TARGETINSTRINFO_H -#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Target/TargetInstrDesc.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/Support/DataTypes.h" -#include -#include namespace llvm { -class MachineInstr; -class TargetMachine; +class MCAsmInfo; class TargetRegisterClass; +class TargetRegisterInfo; class LiveVariables; +class CalleeSavedInfo; +class SDNode; +class SelectionDAG; +class MachineMemOperand; -//--------------------------------------------------------------------------- -// Data types used to define information about a single machine instruction -//--------------------------------------------------------------------------- +template class SmallVectorImpl; -typedef short MachineOpCode; -typedef unsigned InstrSchedClass; //--------------------------------------------------------------------------- -// struct TargetInstrDescriptor: -// Predefined information about each machine instruction. -// Designed to initialized statically. -// - -const unsigned M_BRANCH_FLAG = 1 << 0; -const unsigned M_CALL_FLAG = 1 << 1; -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; -const unsigned M_STORE_FLAG = 1 << 6; -const unsigned M_INDIRECT_FLAG = 1 << 7; -const unsigned M_IMPLICIT_DEF_FLAG = 1 << 8; - -// M_CONVERTIBLE_TO_3_ADDR - This is a 2-address 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 << 9; - -// 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 << 10; - -// 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 << 11; - -// M_USES_CUSTOM_DAG_SCHED_INSERTION - Set if this instruction requires custom -// insertion support when the DAG scheduler is inserting it into a machine basic -// block. -const unsigned M_USES_CUSTOM_DAG_SCHED_INSERTION = 1 << 12; - -// M_VARIABLE_OPS - Set if this instruction can have a variable number of extra -// operands in addition to the minimum number operands specified. -const unsigned M_VARIABLE_OPS = 1 << 13; - -// M_PREDICABLE - Set if this instruction has a predicate operand that -// controls execution. It may be set to 'always'. -const unsigned M_PREDICABLE = 1 << 14; - -// M_REMATERIALIZIBLE - Set if this instruction can be trivally re-materialized -// at any time, e.g. constant generation, load from constant pool. -const unsigned M_REMATERIALIZIBLE = 1 << 15; - -// M_NOT_DUPLICABLE - Set if this instruction cannot be safely duplicated. -// (e.g. instructions with unique labels attached). -const unsigned M_NOT_DUPLICABLE = 1 << 16; - -// M_HAS_OPTIONAL_DEF - Set if this instruction has an optional definition, e.g. -// ARM instructions which can set condition code if 's' bit is set. -const unsigned M_HAS_OPTIONAL_DEF = 1 << 17; - -// 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 -// requires a callback to look up its register class. -const unsigned M_LOOK_UP_PTR_REG_CLASS = 1 << 0; - -/// M_PREDICATE_OPERAND - Set if this is one of the operands that made up of the -/// predicate operand that controls an M_PREDICATED instruction. -const unsigned M_PREDICATE_OPERAND = 1 << 1; - -/// M_OPTIONAL_DEF_OPERAND - Set if this operand is a optional def. /// -const unsigned M_OPTIONAL_DEF_OPERAND = 1 << 2; - -namespace TOI { - // Operand constraints: only "tied_to" for now. - enum OperandConstraint { - TIED_TO = 0 // Must be allocated the same register as. - }; -} - -/// TargetOperandInfo - This holds information about one operand of a machine -/// instruction, indicating the register class for register operands, etc. -/// -class TargetOperandInfo { -public: - /// RegClass - This specifies the register class enumeration of the operand - /// if the operand is a register. If not, this contains 0. - unsigned short RegClass; - unsigned short Flags; - /// Lower 16 bits are used to specify which constraints are set. The higher 16 - /// bits are used to specify the value of constraints (4 bits each). - unsigned int Constraints; - /// Currently no other information. -}; - - -class TargetInstrDescriptor { -public: - MachineOpCode Opcode; // The opcode. - unsigned short numOperands; // Num of args (may be more if variable_ops). - unsigned short numDefs; // Num of args that are definitions. - const char * Name; // Assembly language mnemonic for the opcode. - InstrSchedClass schedClass; // enum identifying instr sched class - unsigned Flags; // flags identifying machine instr class - unsigned TSFlags; // Target Specific Flag values - const unsigned *ImplicitUses; // Registers implicitly read by this instr - const unsigned *ImplicitDefs; // Registers implicitly defined by this instr - const TargetOperandInfo *OpInfo; // 'numOperands' entries about operands. - - /// getOperandConstraint - Returns the value of the specific constraint if - /// it is set. Returns -1 if it is not set. - int getOperandConstraint(unsigned OpNum, - TOI::OperandConstraint Constraint) const { - assert((OpNum < numOperands || (Flags & M_VARIABLE_OPS)) && - "Invalid operand # of TargetInstrInfo"); - if (OpNum < numOperands && - (OpInfo[OpNum].Constraints & (1 << Constraint))) { - unsigned Pos = 16 + Constraint * 4; - return (int)(OpInfo[OpNum].Constraints >> Pos) & 0xf; - } - return -1; - } - - /// findTiedToSrcOperand - Returns the operand that is tied to the specified - /// dest operand. Returns -1 if there isn't one. - int findTiedToSrcOperand(unsigned OpNum) const; -}; - - -//--------------------------------------------------------------------------- -/// -/// TargetInstrInfo - Interface to description of machine instructions +/// TargetInstrInfo - Interface to description of machine instruction set /// class TargetInstrInfo { - const TargetInstrDescriptor* desc; // raw array to allow static init'n - unsigned NumOpcodes; // number of entries in the desc array - unsigned numRealOpCodes; // number of non-dummy op codes + const TargetInstrDesc *Descriptors; // Raw array to allow static init'n + unsigned NumOpcodes; // Number of entries in the desc array TargetInstrInfo(const TargetInstrInfo &); // DO NOT IMPLEMENT void operator=(const TargetInstrInfo &); // DO NOT IMPLEMENT public: - TargetInstrInfo(const TargetInstrDescriptor *desc, unsigned NumOpcodes); + TargetInstrInfo(const TargetInstrDesc *desc, unsigned NumOpcodes); virtual ~TargetInstrInfo(); - // Invariant opcodes: All instruction sets have these as their low opcodes. - enum { - PHI = 0, - INLINEASM = 1, - LABEL = 2, - EXTRACT_SUBREG = 3, - INSERT_SUBREG = 4 - }; - unsigned getNumOpcodes() const { return NumOpcodes; } /// get - Return the machine instruction descriptor that corresponds to the /// specified instruction opcode. /// - const TargetInstrDescriptor& get(MachineOpCode Opcode) const { - assert((unsigned)Opcode < NumOpcodes); - return desc[Opcode]; - } - - const char *getName(MachineOpCode Opcode) const { - return get(Opcode).Name; - } - - int getNumOperands(MachineOpCode Opcode) const { - return get(Opcode).numOperands; - } - - int getNumDefs(MachineOpCode Opcode) const { - return get(Opcode).numDefs; - } - - InstrSchedClass getSchedClass(MachineOpCode Opcode) const { - return get(Opcode).schedClass; - } - - const unsigned *getImplicitUses(MachineOpCode Opcode) const { - return get(Opcode).ImplicitUses; - } - - const unsigned *getImplicitDefs(MachineOpCode Opcode) const { - return get(Opcode).ImplicitDefs; - } - - - // - // Query instruction class flags according to the machine-independent - // flags listed above. - // - bool isReturn(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_RET_FLAG; - } - - bool isCommutableInstr(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_COMMUTABLE; - } - bool isTerminatorInstr(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_TERMINATOR_FLAG; - } - - bool isBranch(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_BRANCH_FLAG; - } - - bool isIndirectBranch(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_INDIRECT_FLAG; - } - - /// isBarrier - Returns true if the specified instruction stops control flow - /// from executing the instruction immediately following it. Examples include - /// unconditional branches and return instructions. - bool isBarrier(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_BARRIER_FLAG; - } - - bool isCall(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_CALL_FLAG; - } - bool isLoad(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_LOAD_FLAG; - } - bool isStore(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_STORE_FLAG; - } - - /// hasDelaySlot - Returns true if the specified instruction has a delay slot - /// which must be filled by the code generator. - bool hasDelaySlot(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_DELAY_SLOT_FLAG; - } - - /// usesCustomDAGSchedInsertionHook - Return true if this instruction requires - /// custom insertion support when the DAG scheduler is inserting it into a - /// machine basic block. - bool usesCustomDAGSchedInsertionHook(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_USES_CUSTOM_DAG_SCHED_INSERTION; - } - - bool hasVariableOperands(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_VARIABLE_OPS; - } - - bool isPredicable(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_PREDICABLE; - } - - bool isNotDuplicable(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_NOT_DUPLICABLE; - } - - bool hasOptionalDef(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_HAS_OPTIONAL_DEF; + const TargetInstrDesc &get(unsigned Opcode) const { + assert(Opcode < NumOpcodes && "Invalid opcode!"); + return Descriptors[Opcode]; } /// 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(MachineInstr *MI) const { - return (MI->getInstrDescriptor()->Flags & M_REMATERIALIZIBLE) && - isReallyTriviallyReMaterializable(MI); + bool isTriviallyReMaterializable(const MachineInstr *MI, + AliasAnalysis *AA = 0) const { + return MI->getOpcode() == TargetOpcode::IMPLICIT_DEF || + (MI->getDesc().isRematerializable() && + (isReallyTriviallyReMaterializable(MI, AA) || + isReallyTriviallyReMaterializableGeneric(MI, AA))); } - /// 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 || - TID->Flags & M_MAY_HAVE_SIDE_EFFECTS)) return true; - if (TID->Flags & M_NEVER_HAS_SIDE_EFFECTS) return false; - 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 - /// 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(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; } - /// 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 { +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: + /// 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& SrcReg, unsigned& DstReg, + unsigned& SrcSubIdx, unsigned& DstSubIdx) const { return false; } -public: - /// getOperandConstraint - Returns the value of the specific constraint if - /// it is set. Returns -1 if it is not set. - int getOperandConstraint(MachineOpCode Opcode, unsigned OpNum, - TOI::OperandConstraint Constraint) const { - return get(Opcode).getOperandConstraint(OpNum, Constraint); + + /// isCoalescableExtInstr - Return true if the instruction is a "coalescable" + /// extension instruction. That is, it's like a copy where it's legal for the + /// source to overlap the destination. e.g. X86::MOVSX64rr32. If this returns + /// true, then it's expected the pre-extension value is available as a subreg + /// of the result register. This also returns the sub-register index in + /// SubIdx. + virtual bool isCoalescableExtInstr(const MachineInstr &MI, + unsigned &SrcReg, unsigned &DstReg, + unsigned &SubIdx) const { + return false; } - /// Return true if the instruction is a register to register move - /// and leave the source and dest operands in the passed parameters. - virtual bool isMoveInstr(const MachineInstr& MI, - unsigned& sourceReg, - unsigned& destReg) const { + /// 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() == TargetOpcode::EXTRACT_SUBREG && + MI.getOperand(0).getReg() == MI.getOperand(1).getReg()) + return true; + + if ((MI.getOpcode() == TargetOpcode::INSERT_SUBREG || + MI.getOpcode() == TargetOpcode::SUBREG_TO_REG) && + MI.getOperand(0).getReg() == MI.getOperand(2).getReg()) + return true; return false; } @@ -367,7 +134,29 @@ public: /// 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; } @@ -376,10 +165,47 @@ public: /// 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; + } + + /// reMaterialize - Re-issue the specified 'original' instruction at the + /// specific location targeting a new destination register. + virtual void reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo *TRI) const = 0; + + /// duplicate - Create a duplicate of the Orig instruction in MF. This is like + /// MachineFunction::CloneMachineInstr(), but the target may update operands + /// that are required to be unique. + /// + /// The instruction must be duplicable as indicated by isNotDuplicable(). + virtual MachineInstr *duplicate(MachineInstr *Orig, + MachineFunction &MF) 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 @@ -392,7 +218,7 @@ public: /// virtual MachineInstr * convertToThreeAddress(MachineFunction::iterator &MFI, - MachineBasicBlock::iterator &MBBI, LiveVariables &LV) const { + MachineBasicBlock::iterator &MBBI, LiveVariables *LV) const { return 0; } @@ -406,7 +232,24 @@ public: /// return a new machine instruction. If an instruction cannot commute, it /// can also return null. /// - virtual MachineInstr *commuteInstruction(MachineInstr *MI) const = 0; + /// If NewMI is true, then a new machine instruction must be created. + /// + virtual MachineInstr *commuteInstruction(MachineInstr *MI, + bool NewMI = false) 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 @@ -417,79 +260,221 @@ public: /// just return false, leaving TBB/FBB null. /// 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 - /// operands can be passed to other TargetInstrInfo methods to create new - /// branches. + /// 3. If this block ends with a conditional branch and it falls through to 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, - std::vector &Cond) const { + SmallVectorImpl &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 + /// This is only invoked in cases where AnalyzeBranch returns success. It /// returns the number of instructions that were removed. virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const { 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 std::vector &Cond) const { + const SmallVectorImpl &Cond) const { assert(0 && "Target didn't implement TargetInstrInfo::InsertBranch!"); return 0; } - /// copyRegToReg - Add a copy between a pair of registers - virtual void copyRegToReg(MachineBasicBlock &MBB, + /// copyRegToReg - Emit instructions to copy between a pair of registers. It + /// returns false if the target does not how to copy between the specified + /// registers. + virtual bool 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!"); + 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, + const TargetRegisterClass *RC) const { + assert(0 && "Target didn't implement TargetInstrInfo::storeRegToStackSlot!"); + } + + /// 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!"); } - /// 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(MachineBasicBlock &MBB) const { + /// 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 &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 &CSI) const { + return false; + } + + /// foldMemoryOperand - Attempt to fold a load or store of the specified stack + /// slot into the specified machine instruction for the specified operand(s). + /// If this is possible, a new instruction is returned with the specified + /// operand folded, otherwise NULL is returned. The client is responsible for + /// removing the old instruction and adding the new one in the instruction + /// stream. + MachineInstr* foldMemoryOperand(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &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. + MachineInstr* foldMemoryOperand(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &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 &Ops, + int FrameIndex) const { + return 0; + } + + /// 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 &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, + const SmallVectorImpl &Ops) const { + return false; + } + + /// unfoldMemoryOperand - Separate a single instruction which folded a load or + /// a store or a load and a store into two or more instruction. If this is + /// 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 &NewMIs) const{ + return false; + } + + virtual bool unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, + SmallVectorImpl &NewNodes) 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. 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, + unsigned *LoadRegIndex = 0) const { + return 0; + } + + /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler + /// to determine if two loads are loading from the same base address. It + /// should only return true if the base pointers are the same and the + /// only differences between the two addresses are the offset. It also returns + /// the offsets by reference. + virtual bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, + int64_t &Offset1, int64_t &Offset2) const { + return false; + } + + /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to + /// determine (in conjuction with areLoadsFromSameBasePtr) if two loads should + /// be scheduled togther. On some targets if two loads are loading from + /// addresses in the same cache line, it's better if they are scheduled + /// together. This function takes two integers that represent the load offsets + /// from the common base address. It returns true if it decides it's desirable + /// to schedule the two loads together. "NumLoads" is the number of loads that + /// have already been scheduled after Load1. + virtual bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, + int64_t Offset1, int64_t Offset2, + unsigned NumLoads) const { return false; } /// ReverseBranchCondition - Reverses the branch condition of the specified /// condition list, returning false on success and true if it cannot be /// reversed. - virtual bool ReverseBranchCondition(std::vector &Cond) const { + virtual + bool ReverseBranchCondition(SmallVectorImpl &Cond) const { return true; } /// 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 { @@ -504,13 +489,13 @@ public: /// instruction. It returns true if the operation was successful. virtual bool PredicateInstruction(MachineInstr *MI, - const std::vector &Pred) const = 0; + const SmallVectorImpl &Pred) const = 0; /// SubsumesPredicate - Returns true if the first specified predicate /// subsumes the second, e.g. GE subsumes GT. virtual - bool SubsumesPredicate(const std::vector &Pred1, - const std::vector &Pred2) const { + bool SubsumesPredicate(const SmallVectorImpl &Pred1, + const SmallVectorImpl &Pred2) const { return false; } @@ -522,13 +507,35 @@ public: 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. + /// + virtual unsigned GetInstSizeInBytes(const MachineInstr *MI) const { + assert(0 && "Target didn't implement TargetInstrInfo::GetInstSize!"); + return 0; + } + + /// 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 @@ -537,13 +544,27 @@ public: /// libcodegen, not in libtarget. class TargetInstrInfoImpl : public TargetInstrInfo { protected: - TargetInstrInfoImpl(const TargetInstrDescriptor *desc, unsigned NumOpcodes) + TargetInstrInfoImpl(const TargetInstrDesc *desc, unsigned NumOpcodes) : TargetInstrInfo(desc, NumOpcodes) {} public: - virtual MachineInstr *commuteInstruction(MachineInstr *MI) const; + virtual MachineInstr *commuteInstruction(MachineInstr *MI, + bool NewMI = false) const; + virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, + unsigned &SrcOpIdx2) const; virtual bool PredicateInstruction(MachineInstr *MI, - const std::vector &Pred) const; - + const SmallVectorImpl &Pred) const; + virtual void reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SubReg, + const MachineInstr *Orig, + const TargetRegisterInfo *TRI) const; + virtual MachineInstr *duplicate(MachineInstr *Orig, + MachineFunction &MF) const; + virtual bool isIdentical(const MachineInstr *MI, + const MachineInstr *Other, + const MachineRegisterInfo *MRI) const; + + virtual unsigned GetFunctionSizeInBytes(const MachineFunction &MF) const; }; } // End llvm namespace