#ifndef LLVM_TARGET_TARGETINSTRDESC_H
#define LLVM_TARGET_TARGETINSTRDESC_H
-#include <cassert>
+#include "llvm/Support/DataTypes.h"
namespace llvm {
+class TargetRegisterClass;
+class TargetRegisterInfo;
+
//===----------------------------------------------------------------------===//
// Machine Operand Flags and Description
//===----------------------------------------------------------------------===//
namespace TOI {
- // Operand constraints: only "tied_to" for now.
+ // Operand constraints
enum OperandConstraint {
- TIED_TO = 0 // Must be allocated the same register as.
+ TIED_TO = 0, // Must be allocated the same register as.
+ EARLY_CLOBBER // Operand is an early clobber register operand
};
/// OperandFlags - These are flags set on operands, but should be considered
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;
+ /// if the operand is a register. If isLookupPtrRegClass is set, then this is
+ /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to
+ /// get a dynamic register class.
+ ///
+ /// NOTE: This member should be considered to be private, all access should go
+ /// through "getRegClass(TRI)" below.
+ short RegClass;
+
+ /// Flags - These are flags from the TOI::OperandFlags enum.
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;
+ unsigned Constraints;
/// Currently no other information.
+ /// getRegClass - Get the register class for the operand, handling resolution
+ /// of "symbolic" pointer register classes etc. If this is not a register
+ /// operand, this returns null.
+ const TargetRegisterClass *getRegClass(const TargetRegisterInfo *TRI) const;
+
+
/// isLookupPtrRegClass - Set if this operand is a pointer value and it
/// requires a callback to look up its register class.
bool isLookupPtrRegClass() const { return Flags&(1 <<TOI::LookupPtrRegClass);}
Terminator,
Branch,
IndirectBranch,
- Predicable,
- NotDuplicable,
+ Compare,
+ MoveImm,
DelaySlot,
- SimpleLoad,
+ FoldableAsLoad,
MayLoad,
MayStore,
+ Predicable,
+ NotDuplicable,
UnmodeledSideEffects,
Commutable,
ConvertibleTo3Addr,
- UsesCustomDAGSchedInserter,
- Rematerializable
+ UsesCustomInserter,
+ Rematerializable,
+ CheapAsAMove,
+ ExtraSrcRegAllocReq,
+ ExtraDefRegAllocReq
};
}
/// points to this struct directly to describe itself.
class TargetInstrDesc {
public:
- unsigned short Opcode; // The opcode number.
+ unsigned short Opcode; // The opcode number
unsigned short NumOperands; // Num of args (may be more if variable_ops)
- unsigned short NumDefs; // Num of args that are definitions.
+ unsigned short NumDefs; // Num of args that are definitions
unsigned short SchedClass; // enum identifying instr sched class
- const char * Name; // Name of the instruction record in td file.
- unsigned Flags; // flags identifying machine instr class
- unsigned TSFlags; // Target Specific Flag values
+ const char * Name; // Name of the instruction record in td file
+ unsigned Flags; // Flags identifying machine instr class
+ uint64_t 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.
+ const TargetRegisterClass **RCBarriers; // Reg classes completely "clobbered"
+ 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.
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;
-
+ /// getRegClass - Returns the register class constraint for OpNum, or NULL.
+ const TargetRegisterClass *getRegClass(unsigned OpNum,
+ const TargetRegisterInfo *TRI) const {
+ return OpNum < NumOperands ? OpInfo[OpNum].getRegClass(TRI) : 0;
+ }
+
/// getOpcode - Return the opcode number for this descriptor.
unsigned getOpcode() const {
return Opcode;
/// getNumDefs - Return the number of MachineOperands that are register
/// definitions. Register definitions always occur at the start of the
- /// machine operand list. This is the number of "outs" in the .td file.
+ /// machine operand list. This is the number of "outs" in the .td file,
+ /// and does not include implicit defs.
unsigned getNumDefs() const {
return NumDefs;
}
return ImplicitUses;
}
+ /// getNumImplicitUses - Return the number of implicit uses this instruction
+ /// has.
+ unsigned getNumImplicitUses() const {
+ if (ImplicitUses == 0) return 0;
+ unsigned i = 0;
+ for (; ImplicitUses[i]; ++i) /*empty*/;
+ return i;
+ }
+
+
/// getImplicitDefs - Return a list of registers that are potentially
/// written by any instance of this machine instruction. For example, on X86,
/// many instructions implicitly set the flags register. In this case, they
const unsigned *getImplicitDefs() const {
return ImplicitDefs;
}
+
+ /// getNumImplicitDefs - Return the number of implicit defs this instruction
+ /// has.
+ unsigned getNumImplicitDefs() const {
+ if (ImplicitDefs == 0) return 0;
+ unsigned i = 0;
+ for (; ImplicitDefs[i]; ++i) /*empty*/;
+ return i;
+ }
+
+ /// hasImplicitUseOfPhysReg - Return true if this instruction implicitly
+ /// uses the specified physical register.
+ bool hasImplicitUseOfPhysReg(unsigned Reg) const {
+ if (const unsigned *ImpUses = ImplicitUses)
+ for (; *ImpUses; ++ImpUses)
+ if (*ImpUses == Reg) return true;
+ return false;
+ }
+
+ /// hasImplicitDefOfPhysReg - Return true if this instruction implicitly
+ /// defines the specified physical register.
+ bool hasImplicitDefOfPhysReg(unsigned Reg) const {
+ if (const unsigned *ImpDefs = ImplicitDefs)
+ for (; *ImpDefs; ++ImpDefs)
+ if (*ImpDefs == Reg) return true;
+ return false;
+ }
+
+ /// getRegClassBarriers - Return a list of register classes that are
+ /// completely clobbered by this machine instruction. For example, on X86
+ /// the call instructions will completely clobber all the registers in the
+ /// fp stack and XMM classes.
+ ///
+ /// This method returns null if the instruction doesn't completely clobber
+ /// any register class.
+ const TargetRegisterClass **getRegClassBarriers() const {
+ return RCBarriers;
+ }
/// getSchedClass - Return the scheduling class for this instruction. The
/// scheduling class is an index into the InstrItineraryData table. This
bool isIndirectBranch() const {
return Flags & (1 << TID::IndirectBranch);
}
-
+
/// isConditionalBranch - Return true if this is a branch which may fall
/// through to the next instruction or may transfer control flow to some other
/// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more
return Flags & (1 << TID::Predicable);
}
+ /// isCompare - Return true if this instruction is a comparison.
+ bool isCompare() const {
+ return Flags & (1 << TID::Compare);
+ }
+
+ /// isMoveImmediate - Return true if this instruction is a move immediate
+ /// (including conditional moves) instruction.
+ bool isMoveImmediate() const {
+ return Flags & (1 << TID::MoveImm);
+ }
+
/// isNotDuplicable - Return true if this instruction cannot be safely
/// duplicated. For example, if the instruction has a unique labels attached
/// to it, duplicating it would cause multiple definition errors.
return Flags & (1 << TID::DelaySlot);
}
- /// isSimpleLoad - Return true for instructions that are simple loads from
- /// memory. This should only be set on instructions that load a value from
- /// memory and return it in their only virtual register definition.
- /// Instructions that return a value loaded from memory and then modified in
- /// some way should not return true for this.
- bool isSimpleLoad() const {
- return Flags & (1 << TID::SimpleLoad);
+ /// canFoldAsLoad - Return true for instructions that can be folded as
+ /// memory operands in other instructions. The most common use for this
+ /// is instructions that are simple loads from memory that don't modify
+ /// the loaded value in any way, but it can also be used for instructions
+ /// that can be expressed as constant-pool loads, such as V_SETALLONES
+ /// on x86, to allow them to be folded when it is beneficial.
+ /// This should only be set on instructions that return a value in their
+ /// only virtual register definition.
+ bool canFoldAsLoad() const {
+ return Flags & (1 << TID::FoldableAsLoad);
}
//===--------------------------------------------------------------------===//
return Flags & (1 << TID::ConvertibleTo3Addr);
}
- /// usesCustomDAGSchedInsertionHook - Return true if this instruction requires
+ /// usesCustomInsertionHook - Return true if this instruction requires
/// custom insertion support when the DAG scheduler is inserting it into a
/// machine basic block. If this is true for the instruction, it basically
/// means that it is a pseudo instruction used at SelectionDAG time that is
///
/// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method
/// is used to insert this into the MachineBasicBlock.
- bool usesCustomDAGSchedInsertionHook() const {
- return Flags & (1 << TID::UsesCustomDAGSchedInserter);
+ bool usesCustomInsertionHook() const {
+ return Flags & (1 << TID::UsesCustomInserter);
}
/// isRematerializable - Returns true if this instruction is a candidate for
bool isRematerializable() const {
return Flags & (1 << TID::Rematerializable);
}
+
+ /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or
+ /// less) than a move instruction. This is useful during certain types of
+ /// optimizations (e.g., remat during two-address conversion or machine licm)
+ /// where we would like to remat or hoist the instruction, but not if it costs
+ /// more than moving the instruction into the appropriate register. Note, we
+ /// are not marking copies from and to the same register class with this flag.
+ bool isAsCheapAsAMove() const {
+ return Flags & (1 << TID::CheapAsAMove);
+ }
+
+ /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands
+ /// have special register allocation requirements that are not captured by the
+ /// operand register classes. e.g. ARM::STRD's two source registers must be an
+ /// even / odd pair, ARM::STM registers have to be in ascending order.
+ /// Post-register allocation passes should not attempt to change allocations
+ /// for sources of instructions with this flag.
+ bool hasExtraSrcRegAllocReq() const {
+ return Flags & (1 << TID::ExtraSrcRegAllocReq);
+ }
+
+ /// hasExtraDefRegAllocReq - Returns true if this instruction def operands
+ /// have special register allocation requirements that are not captured by the
+ /// operand register classes. e.g. ARM::LDRD's two def registers must be an
+ /// even / odd pair, ARM::LDM registers have to be in ascending order.
+ /// Post-register allocation passes should not attempt to change allocations
+ /// for definitions of instructions with this flag.
+ bool hasExtraDefRegAllocReq() const {
+ return Flags & (1 << TID::ExtraDefRegAllocReq);
+ }
};
} // end namespace llvm