X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FTarget%2FTargetInstrInfo.h;h=2f2f4cd575e1f28188fa329f4b861685bfb538b5;hb=320c630c1b55e17fa00249d499f974cb1a4238f8;hp=b8f925eab2134ef8a17bdf38c5a80cd2476869e7;hpb=4ed88eb8229848cd6add06a1ec90e497e382306f;p=oota-llvm.git diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index b8f925eab21..2f2f4cd575e 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -15,6 +15,7 @@ #define LLVM_TARGET_TARGETINSTRINFO_H #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/Support/DataTypes.h" #include #include @@ -23,13 +24,9 @@ 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 @@ -44,69 +41,122 @@ typedef unsigned InstrSchedClass; // 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_BARRIER_FLAG = 1 << 4; -const unsigned M_DELAY_SLOT_FLAG = 1 << 5; -const unsigned M_CC_FLAG = 1 << 6; -const unsigned M_LOAD_FLAG = 1 << 7; -const unsigned M_STORE_FLAG = 1 << 8; +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_2_ADDR_FLAG - 3-addr instructions which really work like 2-addr ones. -const unsigned M_2_ADDR_FLAG = 1 << 9; - -// M_CONVERTIBLE_TO_3_ADDR - This is a M_2_ADDR_FLAG instruction which can be +// 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 << 10; +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 << 11; +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 << 12; +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 << 13; +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 of the operand if the - /// operand is a register. If not, this contains null. - const TargetRegisterClass *RegClass; - + /// 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. - 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 IMMED 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; }; @@ -128,7 +178,10 @@ public: // Invariant opcodes: All instruction sets have these as their low opcodes. enum { PHI = 0, - INLINEASM = 1 + INLINEASM = 1, + LABEL = 2, + EXTRACT_SUBREG = 3, + INSERT_SUBREG = 4 }; unsigned getNumOpcodes() const { return NumOpcodes; } @@ -149,6 +202,10 @@ public: return get(Opcode).numOperands; } + int getNumDefs(MachineOpCode Opcode) const { + return get(Opcode).numDefs; + } + InstrSchedClass getSchedClass(MachineOpCode Opcode) const { return get(Opcode).schedClass; } @@ -170,10 +227,10 @@ public: return get(Opcode).Flags & M_RET_FLAG; } - bool isTwoAddrInstr(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_2_ADDR_FLAG; + bool isCommutableInstr(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_COMMUTABLE; } - bool isTerminatorInstr(unsigned Opcode) const { + bool isTerminatorInstr(MachineOpCode Opcode) const { return get(Opcode).Flags & M_TERMINATOR_FLAG; } @@ -181,6 +238,10 @@ public: 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. @@ -198,13 +259,64 @@ public: 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(unsigned Opcode) const { + 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; + } + + /// 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); + } + +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; + } + +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); + } + /// 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, @@ -212,18 +324,38 @@ public: unsigned& destReg) const { return false; } + + /// 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; + } + + /// 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 a true - /// three-address instruction on demand. This allows the X86 target (for + /// 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. /// /// This method returns a null pointer if the transformation cannot be - /// performed, otherwise it returns the new instruction. + /// performed, otherwise it returns the last new instruction. /// - virtual MachineInstr *convertToThreeAddress(MachineInstr *TA) const { + virtual MachineInstr * + convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, LiveVariables &LV) const { return 0; } @@ -239,86 +371,117 @@ public: /// virtual MachineInstr *commuteInstruction(MachineInstr *MI) const; - /// Insert a goto (unconditional branch) sequence to TMBB, at the - /// end of MBB - virtual void insertGoto(MachineBasicBlock& MBB, - MachineBasicBlock& TMBB) const { - assert(0 && "Target didn't implement insertGoto!"); - } - - /// Reverses the branch condition of the MachineInstr pointed by - /// MI. The instruction is replaced and the new MI is returned. - virtual MachineBasicBlock::iterator - reverseBranchCondition(MachineBasicBlock::iterator MI) const { - assert(0 && "Target didn't implement reverseBranchCondition!"); - abort(); - return MI; + /// 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; } - - //------------------------------------------------------------------------- - // Code generation support for creating individual machine instructions - // - // WARNING: These methods are Sparc specific - // - // DO NOT USE ANY OF THESE METHODS THEY ARE DEPRECATED! - // - //------------------------------------------------------------------------- - - unsigned getNumDelaySlots(MachineOpCode Opcode) const { - return get(Opcode).numDelaySlots; - } - bool isCCInstr(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_CC_FLAG; + /// 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; } - bool isNop(MachineOpCode Opcode) const { - return get(Opcode).Flags & M_NOP_FLAG; + + /// 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; } - /// hasDelaySlot - Returns true if the specified instruction has a delay slot - /// which must be filled by the code generator. - bool hasDelaySlot(unsigned Opcode) const { - return get(Opcode).Flags & M_DELAY_SLOT_FLAG; + /// 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; } - - virtual bool hasResultInterlock(MachineOpCode Opcode) const { + + /// 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; } + + /// 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(); + } - // - // Latencies for individual instructions and instruction pairs - // - virtual int minLatency(MachineOpCode Opcode) const { - return get(Opcode).latency; + /// isPredicated - Returns true if the instruction is already predicated. + /// + virtual bool isPredicated(const MachineInstr *MI) const { + return false; } - virtual int maxLatency(MachineOpCode Opcode) const { - return get(Opcode).latency; + /// 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; } - // - // 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" + /// 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; } - // Check if the specified constant fits in the immediate field - // of this machine instruction - // - virtual bool constantFitsInImmedField(MachineOpCode Opcode, - int64_t intValue) const; - - // Return the largest positive constant that can be held in the IMMED 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; + /// 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 } };