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.

llvm-svn: 19609
This commit is contained in:
Chris Lattner 2005-01-16 07:27:49 +00:00
parent 71e1e6220c
commit 328bc38c5c
1 changed files with 66 additions and 19 deletions

View File

@ -66,15 +66,29 @@ class TargetLowering {
/// by the system, this holds the same type (e.g. i32 -> i32). /// by the system, this holds the same type (e.g. i32 -> i32).
MVT::ValueType TransformToType[MVT::LAST_VALUETYPE]; 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<double> LegalFPImmediates;
std::vector<std::pair<MVT::ValueType, std::vector<std::pair<MVT::ValueType,
TargetRegisterClass*> > AvailableRegClasses; TargetRegisterClass*> > AvailableRegClasses;
public: 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); TargetLowering(TargetMachine &TM);
virtual ~TargetLowering() {} virtual ~TargetLowering();
TargetMachine &getTargetMachine() const { return TM; } TargetMachine &getTargetMachine() const { return TM; }
const TargetData &getTargetData() const { return TD; } const TargetData &getTargetData() const { return TD; }
@ -82,7 +96,7 @@ public:
bool isLittleEndian() const { return IsLittleEndian; } bool isLittleEndian() const { return IsLittleEndian; }
MVT::ValueType getPointerTy() const { return PointerTy; } MVT::ValueType getPointerTy() const { return PointerTy; }
TargetRegisterClass *getRegClassFor(MVT::ValueType VT) { TargetRegisterClass *getRegClassFor(MVT::ValueType VT) const {
TargetRegisterClass *RC = RegClassForVT[VT]; TargetRegisterClass *RC = RegClassForVT[VT];
assert(RC && "This value type is not natively supported!"); assert(RC && "This value type is not natively supported!");
return RC; return RC;
@ -91,16 +105,16 @@ public:
/// hasNativeSupportFor - Return true if the target has native support for the /// hasNativeSupportFor - Return true if the target has native support for the
/// specified value type. This means that it has a register that directly /// specified value type. This means that it has a register that directly
/// holds it without promotions or expansions. /// holds it without promotions or expansions.
bool hasNativeSupportFor(MVT::ValueType VT) { bool hasNativeSupportFor(MVT::ValueType VT) const {
return RegClassForVT[VT] != 0; return RegClassForVT[VT] != 0;
} }
/// getTypeAction - Return how we should legalize values of this type, either /// 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 /// it is already legal (return 'Legal') or we need to promote it to a larger
/// (return 1), or we need to expand it into multiple registers of smaller /// type (return 'Promote'), or we need to expand it into multiple registers
/// integer type (return 2). /// of smaller integer type (return 'Expand'). 'Custom' is not an option.
unsigned getTypeAction(MVT::ValueType VT) const { LegalizeAction getTypeAction(MVT::ValueType VT) const {
return (ValueTypeActions >> (2*VT)) & 3; return (LegalizeAction)((ValueTypeActions >> (2*VT)) & 3);
} }
unsigned getValueTypeActions() const { return ValueTypeActions; } unsigned getValueTypeActions() const { return ValueTypeActions; }
@ -109,7 +123,7 @@ public:
/// returns the larger type to promote to. For types that are larger than the /// 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 /// largest integer register, this contains one step in the expansion to get
/// to the smaller register. /// to the smaller register.
MVT::ValueType getTypeToTransformTo(MVT::ValueType VT) { MVT::ValueType getTypeToTransformTo(MVT::ValueType VT) const {
return TransformToType[VT]; return TransformToType[VT];
} }
@ -121,11 +135,36 @@ public:
return LegalFPImmediates.end(); return LegalFPImmediates.end();
} }
bool isOperationSupported(unsigned Op, MVT::ValueType VT) { /// getOperationAction - Return how this operation should be
return (UnsupportedOps[Op] & (1 << VT)) == 0; 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()) { switch (Ty->getTypeID()) {
default: assert(0 && "Unknown type!"); default: assert(0 && "Unknown type!");
case Type::VoidTyID: return MVT::isVoid; case Type::VoidTyID: return MVT::isVoid;
@ -171,10 +210,13 @@ protected:
/// this allows us to compute derived properties we expose. /// this allows us to compute derived properties we expose.
void computeRegisterProperties(); void computeRegisterProperties();
/// setOperationAction - Indicate that the specified operation does not work
void setOperationUnsupported(unsigned Op, MVT::ValueType VT) { /// with the specified type and indicate what to do about it.
assert(VT < 16 && "Too many value types!"); void setOperationAction(unsigned Op, MVT::ValueType VT,
UnsupportedOps[Op] |= 1 << 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 /// addLegalFPImmediate - Indicate that this target can instruction select
@ -183,7 +225,6 @@ protected:
LegalFPImmediates.push_back(Imm); LegalFPImmediates.push_back(Imm);
} }
public: public:
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
@ -235,6 +276,12 @@ public:
virtual std::pair<SDOperand, SDOperand> virtual std::pair<SDOperand, SDOperand>
LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
SelectionDAG &DAG); 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 } // end llvm namespace