X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FTarget%2FTargetInstrInfo.h;h=2f2f4cd575e1f28188fa329f4b861685bfb538b5;hb=320c630c1b55e17fa00249d499f974cb1a4238f8;hp=c6afba5a15624ddb3cc9dd4cb9e7cd2a65a20198;hpb=d0fde30ce850b78371fd1386338350591f9ff494;p=oota-llvm.git diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index c6afba5a156..2f2f4cd575e 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -1,10 +1,10 @@ //===-- llvm/Target/TargetInstrInfo.h - Instruction Info --------*- C++ -*-===// -// +// // 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 describes the target machine instructions to the code generator. @@ -14,7 +14,9 @@ #ifndef LLVM_TARGET_TARGETINSTRINFO_H #define LLVM_TARGET_TARGETINSTRINFO_H -#include "Support/DataTypes.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Support/DataTypes.h" #include #include @@ -22,398 +24,464 @@ namespace llvm { class MachineInstr; class TargetMachine; -class Value; -class Type; -class Instruction; -class Constant; -class Function; class MachineCodeForInstruction; +class TargetRegisterClass; +class LiveVariables; //--------------------------------------------------------------------------- // Data types used to define information about a single machine instruction //--------------------------------------------------------------------------- -typedef int MachineOpCode; +typedef short MachineOpCode; typedef unsigned InstrSchedClass; -const MachineOpCode INVALID_MACHINE_OPCODE = -1; - - //--------------------------------------------------------------------------- // struct TargetInstrDescriptor: -// Predefined information about each machine instruction. -// Designed to initialized statically. +// Predefined information about each machine instruction. +// Designed to initialized statically. // -const unsigned M_NOP_FLAG = 1 << 0; -const unsigned M_BRANCH_FLAG = 1 << 1; -const unsigned M_CALL_FLAG = 1 << 2; -const unsigned M_RET_FLAG = 1 << 3; -const unsigned M_ARITH_FLAG = 1 << 4; -const unsigned M_CC_FLAG = 1 << 6; -const unsigned M_LOGICAL_FLAG = 1 << 6; -const unsigned M_INT_FLAG = 1 << 7; -const unsigned M_FLOAT_FLAG = 1 << 8; -const unsigned M_CONDL_FLAG = 1 << 9; -const unsigned M_LOAD_FLAG = 1 << 10; -const unsigned M_PREFETCH_FLAG = 1 << 11; -const unsigned M_STORE_FLAG = 1 << 12; -const unsigned M_DUMMY_PHI_FLAG = 1 << 13; -const unsigned M_PSEUDO_FLAG = 1 << 14; // Pseudo instruction -// 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_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; + +// 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 << 7; + +// 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 << 8; // 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 << 9; + +// 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 << 10; + +// 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 << 11; + +// M_PREDICABLE - Set if this instruction has a predicate operand that +// controls execution. It may be set to 'always'. +const unsigned M_PREDICABLE = 1 << 12; + +// 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 << 13; + +// M_NOT_DUPLICABLE - Set if this instruction cannot be safely duplicated. +// (e.g. instructions with unique labels attached). +const unsigned M_NOT_DUPLICABLE = 1 << 14; + +// 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 << 15; + +// 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. +}; -struct TargetInstrDescriptor { + +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. - int numOperands; // Number of args; -1 if variable #args - int resultPos; // Position of the result; -1 if no result - unsigned maxImmedConst; // Largest +ve constant in IMMMED field or 0. - bool immedIsSignExtended; // Is IMMED field sign-extended? If so, - // smallest -ve value is -(maxImmedConst+1). - unsigned numDelaySlots; // Number of delay slots after instruction - unsigned latency; // Latency in machine cycles 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 -/// +/// class TargetInstrInfo { const TargetInstrDescriptor* desc; // raw array to allow static init'n - unsigned descSize; // number of entries in the desc array + unsigned NumOpcodes; // number of entries in the desc array unsigned numRealOpCodes; // number of non-dummy op codes - + TargetInstrInfo(const TargetInstrInfo &); // DO NOT IMPLEMENT void operator=(const TargetInstrInfo &); // DO NOT IMPLEMENT public: - TargetInstrInfo(const TargetInstrDescriptor *desc, unsigned descSize, - unsigned numRealOpCodes); + TargetInstrInfo(const TargetInstrDescriptor *desc, unsigned NumOpcodes); virtual ~TargetInstrInfo(); - // Invariant: All instruction sets use opcode #0 as the PHI instruction - enum { PHI = 0 }; - - unsigned getNumRealOpCodes() const { return numRealOpCodes; } - unsigned getNumTotalOpCodes() const { return descSize; } - + // 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(opCode >= 0 && opCode < (int)descSize); - return desc[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; + const char *getName(MachineOpCode Opcode) const { + return get(Opcode).Name; } - - int getResultPos(MachineOpCode opCode) const { - return get(opCode).resultPos; + + int getNumOperands(MachineOpCode Opcode) const { + return get(Opcode).numOperands; } - - unsigned getNumDelaySlots(MachineOpCode opCode) const { - return get(opCode).numDelaySlots; + + int getNumDefs(MachineOpCode Opcode) const { + return get(Opcode).numDefs; } - - InstrSchedClass getSchedClass(MachineOpCode opCode) const { - return get(opCode).schedClass; + + InstrSchedClass getSchedClass(MachineOpCode Opcode) const { + return get(Opcode).schedClass; } - const unsigned *getImplicitUses(MachineOpCode opCode) const { - return get(opCode).ImplicitUses; + const unsigned *getImplicitUses(MachineOpCode Opcode) const { + return get(Opcode).ImplicitUses; } - const unsigned *getImplicitDefs(MachineOpCode opCode) const { - return get(opCode).ImplicitDefs; + const unsigned *getImplicitDefs(MachineOpCode Opcode) const { + return get(Opcode).ImplicitDefs; } + // // Query instruction class flags according to the machine-independent // flags listed above. - // - bool isNop(MachineOpCode opCode) const { - return get(opCode).Flags & M_NOP_FLAG; - } - bool isBranch(MachineOpCode opCode) const { - return get(opCode).Flags & M_BRANCH_FLAG; - } - bool isCall(MachineOpCode opCode) const { - return get(opCode).Flags & M_CALL_FLAG; - } - bool isReturn(MachineOpCode opCode) const { - return get(opCode).Flags & M_RET_FLAG; - } - bool isControlFlow(MachineOpCode opCode) const { - return get(opCode).Flags & M_BRANCH_FLAG - || get(opCode).Flags & M_CALL_FLAG - || get(opCode).Flags & M_RET_FLAG; - } - bool isArith(MachineOpCode opCode) const { - return get(opCode).Flags & M_ARITH_FLAG; + // + bool isReturn(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_RET_FLAG; } - bool isCCInstr(MachineOpCode opCode) const { - return get(opCode).Flags & M_CC_FLAG; + + bool isCommutableInstr(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_COMMUTABLE; } - bool isLogical(MachineOpCode opCode) const { - return get(opCode).Flags & M_LOGICAL_FLAG; + bool isTerminatorInstr(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_TERMINATOR_FLAG; } - bool isIntInstr(MachineOpCode opCode) const { - return get(opCode).Flags & M_INT_FLAG; + + bool isBranch(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_BRANCH_FLAG; } - bool isFloatInstr(MachineOpCode opCode) const { - return get(opCode).Flags & M_FLOAT_FLAG; + + bool isIndirectBranch(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_INDIRECT_FLAG; } - bool isConditional(MachineOpCode opCode) const { - return get(opCode).Flags & M_CONDL_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 isLoad(MachineOpCode opCode) const { - return get(opCode).Flags & M_LOAD_FLAG; + + bool isCall(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_CALL_FLAG; } - bool isPrefetch(MachineOpCode opCode) const { - return get(opCode).Flags & M_PREFETCH_FLAG; + bool isLoad(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_LOAD_FLAG; } - bool isLoadOrPrefetch(MachineOpCode opCode) const { - return get(opCode).Flags & M_LOAD_FLAG - || get(opCode).Flags & M_PREFETCH_FLAG; + bool isStore(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_STORE_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; } - bool isMemoryAccess(MachineOpCode opCode) const { - return get(opCode).Flags & M_LOAD_FLAG - || get(opCode).Flags & M_PREFETCH_FLAG - || get(opCode).Flags & M_STORE_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 isDummyPhiInstr(MachineOpCode opCode) const { - return get(opCode).Flags & M_DUMMY_PHI_FLAG; + + bool hasVariableOperands(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_VARIABLE_OPS; } - bool isPseudoInstr(MachineOpCode opCode) const { - return get(opCode).Flags & M_PSEUDO_FLAG; + + bool isPredicable(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_PREDICABLE; } - bool isTwoAddrInstr(MachineOpCode opCode) const { - return get(opCode).Flags & M_2_ADDR_FLAG; + + bool isNotDuplicable(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_NOT_DUPLICABLE; } - bool isTerminatorInstr(unsigned Opcode) const { - return get(Opcode).Flags & M_TERMINATOR_FLAG; + + bool hasOptionalDef(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_HAS_OPTIONAL_DEF; } - // Check if an instruction can be issued before its operands are ready, - // or if a subsequent instruction that uses its result can be issued - // before the results are ready. - // Default to true since most instructions on many architectures allow this. - // - virtual bool hasOperandInterlock(MachineOpCode opCode) const { - return true; + /// hasNoSideEffects - Return true if the instruction is trivially + /// rematerializable, meaning it has no side effects and requires no operands + /// that aren't always available. + bool hasNoSideEffects(MachineInstr *MI) const { + return (MI->getInstrDescriptor()->Flags & M_REMATERIALIZIBLE) && + isTriviallyReMaterializable(MI); } - - virtual bool hasResultInterlock(MachineOpCode opCode) const { + +protected: + /// isTriviallyReMaterializable - 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 isTriviallyReMaterializable(MachineInstr *MI) const { return true; } - - // - // Latencies for individual instructions and instruction pairs - // - virtual int minLatency(MachineOpCode opCode) const { - return get(opCode).latency; - } - - virtual int maxLatency(MachineOpCode opCode) const { - return get(opCode).latency; + +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); } - // - // Which operand holds an immediate constant? Returns -1 if none - // - virtual int getImmedConstantPos(MachineOpCode opCode) const { - return -1; // immediate position is machine specific, so say -1 == "none" + /// 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 { + return false; } - // Check if the specified constant fits in the immediate field - // of this machine instruction - // - virtual bool constantFitsInImmedField(MachineOpCode opCode, - int64_t intValue) const; + /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// load from a stack slot, return the virtual or physical register number of + /// 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{ + return 0; + } - // Return the largest +ve constant that can be held in the IMMMED field - // of this machine instruction. - // isSignExtended is set to true if the value is sign-extended before use - // (this is true for all immediate fields in SPARC instructions). - // Return 0 if the instruction has no IMMED field. - // - virtual uint64_t maxImmedConstant(MachineOpCode opCode, - bool &isSignExtended) const { - isSignExtended = get(opCode).immedIsSignExtended; - return get(opCode).maxImmedConst; - } - - //------------------------------------------------------------------------- - // Queries about representation of LLVM quantities (e.g., constants) - //------------------------------------------------------------------------- - - /// ConstantTypeMustBeLoaded - Test if this type of constant must be loaded - /// from memory into a register, i.e., cannot be set bitwise in register and - /// cannot use immediate fields of instructions. Note that this only makes - /// sense for primitive types. + /// isStoreToStackSlot - If the specified machine instruction is a direct + /// store to a stack slot, return the virtual or physical register number of + /// 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 { + return 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 + /// three-address instructions 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. /// - virtual bool ConstantTypeMustBeLoaded(const Constant* CV) const; - - // Test if this constant may not fit in the immediate field of the - // machine instructions (probably) generated for this instruction. - // - virtual bool ConstantMayNotFitInImmedField(const Constant* CV, - const Instruction* I) const { - return true; // safe but very conservative + /// This method returns a null pointer if the transformation cannot be + /// performed, otherwise it returns the last new instruction. + /// + virtual MachineInstr * + convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, LiveVariables &LV) const { + return 0; } - - /// createNOPinstr - returns the target's implementation of NOP, which is - /// usually a pseudo-instruction, implemented by a degenerate version of - /// another instruction, e.g. X86: xchg ax, ax; SparcV9: sethi g0, 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. /// - virtual MachineInstr* createNOPinstr() const = 0; - - /// isNOPinstr - not having a special NOP opcode, we need to know if a given - /// instruction is interpreted as an `official' NOP instr, i.e., there may be - /// more than one way to `do nothing' but only one canonical way to slack off. + /// 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 bool isNOPinstr(const MachineInstr &MI) const = 0; + virtual MachineInstr *commuteInstruction(MachineInstr *MI) const; - //------------------------------------------------------------------------- - // Code generation support for creating individual machine instructions - // - // WARNING: These methods are Sparc specific - // - //------------------------------------------------------------------------- - - // Get certain common op codes for the current target. this and all the - // Create* methods below should be moved to a machine code generation class - // - virtual MachineOpCode getNOPOpCode() const { abort(); } - - // Get the value of an integral constant in the form that must - // be put into the machine register. The specified constant is interpreted - // as (i.e., converted if necessary to) the specified destination type. The - // result is always returned as an uint64_t, since the representation of - // int64_t and uint64_t are identical. The argument can be any known const. - // - // isValidConstant is set to true if a valid constant was found. - // - virtual uint64_t ConvertConstantToIntType(const TargetMachine &target, - const Value *V, - const Type *destType, - bool &isValidConstant) const { - abort(); + /// 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 + /// implemented for a target). Upon success, this returns false and returns + /// with the following information in various cases: + /// + /// 1. If this block ends with no branches (it just falls through to its succ) + /// 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. + /// + /// Note that RemoveBranch and InsertBranch must be implemented to support + /// cases where this method returns success. + /// + virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + std::vector &Cond) const { + return true; } - - // Create an instruction sequence to put the constant `val' into - // the virtual register `dest'. `val' may be a Constant or a - // GlobalValue, viz., the constant address of a global variable or function. - // The generated instructions are returned in `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Symbolic constants or constants that must be accessed from memory - // are added to the constant pool via MachineFunction::get(F). - // - virtual void CreateCodeToLoadConst(const TargetMachine& target, - Function* F, - Value* val, - Instruction* dest, - std::vector& mvec, - MachineCodeForInstruction& mcfi) const { - abort(); + + /// 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. + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const { + assert(0 && "Target didn't implement TargetInstrInfo::RemoveBranch!"); + return 0; } - // Create an instruction sequence to copy an integer value `val' - // to a floating point value `dest' by copying to memory and back. - // val must be an integral type. dest must be a Float or Double. - // The generated instructions are returned in `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Any stack space required is allocated via mcff. - // - virtual void CreateCodeToCopyIntToFloat(const TargetMachine& target, - Function* F, - Value* val, - Instruction* dest, - std::vector& mvec, - MachineCodeForInstruction& MI) const { - abort(); + /// 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. + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const std::vector &Cond) const { + assert(0 && "Target didn't implement TargetInstrInfo::InsertBranch!"); + return 0; } - - // Similarly, create an instruction sequence to copy an FP value - // `val' to an integer value `dest' by copying to memory and back. - // The generated instructions are returned in `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Any stack space required is allocated via mcff. - // - virtual void CreateCodeToCopyFloatToInt(const TargetMachine& target, - Function* F, - Value* val, - Instruction* dest, - std::vector& mvec, - MachineCodeForInstruction& MI) const { - abort(); + + /// 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 { + 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 { + return true; } - // Create instruction(s) to copy src to dest, for arbitrary types - // The generated instructions are returned in `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Any stack space required is allocated via mcff. - // - virtual void CreateCopyInstructionsByType(const TargetMachine& target, - Function* F, - Value* src, - Instruction* dest, - std::vector& mvec, - MachineCodeForInstruction& MI) const { + /// 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(); } - // Create instruction sequence to produce a sign-extended register value - // from an arbitrary sized value (sized in bits, not bytes). - // The generated instructions are appended to `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Any stack space required is allocated via mcff. - // - virtual void CreateSignExtensionInstructions(const TargetMachine& target, - Function* F, - Value* srcVal, - Value* destVal, - unsigned numLowBits, - std::vector& mvec, - MachineCodeForInstruction& MI) const { - abort(); + /// isPredicated - Returns true if the instruction is already predicated. + /// + virtual bool isPredicated(const MachineInstr *MI) const { + return false; + } + + /// isUnpredicatedTerminator - Returns true if the instruction is a + /// terminator instruction that has not been predicated. + virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const; + + /// PredicateInstruction - Convert the instruction into a predicated + /// instruction. It returns true if the operation was successful. + virtual + bool PredicateInstruction(MachineInstr *MI, + const std::vector &Pred) const; + + /// 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 { + return false; + } + + /// DefinesPredicate - If the specified instruction defines any predicate + /// or condition code register(s) used for predication, returns true as well + /// as the definition predicate(s) by reference. + virtual bool DefinesPredicate(MachineInstr *MI, + std::vector &Pred) const { + return false; } - // Create instruction sequence to produce a zero-extended register value - // from an arbitrary sized value (sized in bits, not bytes). - // The generated instructions are appended to `mvec'. - // Any temp. registers (TmpInstruction) created are recorded in mcfi. - // Any stack space required is allocated via mcff. - // - virtual void CreateZeroExtensionInstructions(const TargetMachine& target, - Function* F, - Value* srcVal, - Value* destVal, - unsigned srcSizeInBits, - std::vector& mvec, - MachineCodeForInstruction& mcfi) const { + /// 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 } };