Revamp supported ops. Instead of just being supported or not, we now keep

track of how to deal with it, and provide the target with a hook that they
can use to legalize arbitrary operations in arbitrary ways.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19609 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2005-01-16 07:27:49 +00:00
parent cd7c1cae1c
commit 7e5ee40979

View File

@ -66,15 +66,29 @@ class TargetLowering {
/// by the system, this holds the same type (e.g. i32 -> i32).
MVT::ValueType TransformToType[MVT::LAST_VALUETYPE];
unsigned short UnsupportedOps[128];
/// OpActions - For each operation and each value type, keep a LegalizeAction
/// that indicates how instruction selection should deal with the operation.
/// Most operations are Legal (aka, supported natively by the target), but
/// operations that are not should be described. Note that operations on
/// non-legal value types are not described here.
unsigned OpActions[128];
std::vector<double> LegalFPImmediates;
std::vector<std::pair<MVT::ValueType,
TargetRegisterClass*> > AvailableRegClasses;
public:
/// LegalizeAction - This enum indicates whether operations are valid for a
/// target, and if not, what action should be used to make them valid.
enum LegalizeAction {
Legal, // The target natively supports this operation.
Promote, // This operation should be executed in a larger type.
Expand, // Try to expand this to other ops, otherwise use a libcall.
Custom, // Use the LowerOperation hook to implement custom lowering.
};
TargetLowering(TargetMachine &TM);
virtual ~TargetLowering() {}
virtual ~TargetLowering();
TargetMachine &getTargetMachine() const { return TM; }
const TargetData &getTargetData() const { return TD; }
@ -82,7 +96,7 @@ public:
bool isLittleEndian() const { return IsLittleEndian; }
MVT::ValueType getPointerTy() const { return PointerTy; }
TargetRegisterClass *getRegClassFor(MVT::ValueType VT) {
TargetRegisterClass *getRegClassFor(MVT::ValueType VT) const {
TargetRegisterClass *RC = RegClassForVT[VT];
assert(RC && "This value type is not natively supported!");
return RC;
@ -91,16 +105,16 @@ public:
/// hasNativeSupportFor - Return true if the target has native support for the
/// specified value type. This means that it has a register that directly
/// holds it without promotions or expansions.
bool hasNativeSupportFor(MVT::ValueType VT) {
bool hasNativeSupportFor(MVT::ValueType VT) const {
return RegClassForVT[VT] != 0;
}
/// getTypeAction - Return how we should legalize values of this type, either
/// it is already legal (return 0) or we need to promote it to a larger type
/// (return 1), or we need to expand it into multiple registers of smaller
/// integer type (return 2).
unsigned getTypeAction(MVT::ValueType VT) const {
return (ValueTypeActions >> (2*VT)) & 3;
/// it is already legal (return 'Legal') or we need to promote it to a larger
/// type (return 'Promote'), or we need to expand it into multiple registers
/// of smaller integer type (return 'Expand'). 'Custom' is not an option.
LegalizeAction getTypeAction(MVT::ValueType VT) const {
return (LegalizeAction)((ValueTypeActions >> (2*VT)) & 3);
}
unsigned getValueTypeActions() const { return ValueTypeActions; }
@ -109,7 +123,7 @@ public:
/// returns the larger type to promote to. For types that are larger than the
/// largest integer register, this contains one step in the expansion to get
/// to the smaller register.
MVT::ValueType getTypeToTransformTo(MVT::ValueType VT) {
MVT::ValueType getTypeToTransformTo(MVT::ValueType VT) const {
return TransformToType[VT];
}
@ -120,12 +134,37 @@ public:
legal_fpimm_iterator legal_fpimm_end() const {
return LegalFPImmediates.end();
}
bool isOperationSupported(unsigned Op, MVT::ValueType VT) {
return (UnsupportedOps[Op] & (1 << VT)) == 0;
/// getOperationAction - Return how this operation should be
LegalizeAction getOperationAction(unsigned Op, MVT::ValueType VT) const {
return (LegalizeAction)((OpActions[Op] >> (2*VT)) & 3);
}
MVT::ValueType getValueType(const Type *Ty) {
/// hasNativeSupportForOperation - Return true if this operation is legal for
/// this type.
///
bool hasNativeSupportForOperation(unsigned Op, MVT::ValueType VT) const {
return getOperationAction(Op, VT) == Legal;
}
/// getTypeToPromoteTo - If the action for this operation is to promote, this
/// method returns the ValueType to promote to.
MVT::ValueType getTypeToPromoteTo(unsigned Op, MVT::ValueType VT) const {
assert(getOperationAction(Op, VT) == Promote &&
"This operation isn't promoted!");
MVT::ValueType NVT = VT;
do {
NVT = (MVT::ValueType)(NVT+1);
assert(MVT::isInteger(NVT) == MVT::isInteger(VT) && NVT != MVT::isVoid &&
"Didn't find type to promote to!");
} while (!hasNativeSupportFor(NVT) ||
getOperationAction(Op, NVT) == Promote);
return NVT;
}
/// getValueType - Return the MVT::ValueType corresponding to this LLVM type.
/// This is fixed by the LLVM operations except for the pointer size.
MVT::ValueType getValueType(const Type *Ty) const {
switch (Ty->getTypeID()) {
default: assert(0 && "Unknown type!");
case Type::VoidTyID: return MVT::isVoid;
@ -171,10 +210,13 @@ protected:
/// this allows us to compute derived properties we expose.
void computeRegisterProperties();
void setOperationUnsupported(unsigned Op, MVT::ValueType VT) {
assert(VT < 16 && "Too many value types!");
UnsupportedOps[Op] |= 1 << VT;
/// setOperationAction - Indicate that the specified operation does not work
/// with the specified type and indicate what to do about it.
void setOperationAction(unsigned Op, MVT::ValueType VT,
LegalizeAction Action) {
assert(VT < 16 && Op < sizeof(OpActions)/sizeof(OpActions[0]) &&
"Table isn't big enough!");
OpActions[Op] |= Action << VT*2;
}
/// addLegalFPImmediate - Indicate that this target can instruction select
@ -182,7 +224,6 @@ protected:
void addLegalFPImmediate(double Imm) {
LegalFPImmediates.push_back(Imm);
}
public:
@ -235,6 +276,12 @@ public:
virtual std::pair<SDOperand, SDOperand>
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG);
/// LowerOperation - For operations that are unsupported by the target, and
/// which are registered to use 'custom' lowering. This callback is invoked.
/// If the target has no operations that require custom lowering, it need not
/// implement this. The default implementation of this aborts.
virtual SDOperand LowerOperation(SDOperand Op);
};
} // end llvm namespace