diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index eb7814ef9a2..47ba9407957 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -53,7 +53,19 @@ class TargetLowering { /// each ValueType the target supports natively. TargetRegisterClass *RegClassForVT[MVT::LAST_VALUETYPE]; unsigned char NumElementsForVT[MVT::LAST_VALUETYPE]; - + + /// ValueTypeActions - This is a bitvector that contains two bits for each + /// value type, where the two bits correspond to the LegalizeAction enum. + /// This can be queried with "getTypeAction(VT)". + unsigned ValueTypeActions; + + /// TransformToType - For any value types we are promoting or expanding, this + /// contains the value type that we are changing to. For Expanded types, this + /// contains one step of the expand (e.g. i64 -> i32), even if there are + /// multiple steps required (e.g. i64 -> i16). For types natively supported + /// by the system, this holds the same type (e.g. i32 -> i32). + MVT::ValueType TransformToType[MVT::LAST_VALUETYPE]; + unsigned short UnsupportedOps[128]; std::vector LegalFPImmediates; @@ -76,10 +88,30 @@ public: return RC; } - /// hasNativeSupportFor + /// 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) { 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; + } + unsigned getValueTypeActions() const { return ValueTypeActions; } + + /// getTypeToTransformTo - For types supported by the target, this is an + /// identity function. For types that must be promoted to larger types, this + /// 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) { + return TransformToType[VT]; + } typedef std::vector::const_iterator legal_fpimm_iterator; legal_fpimm_iterator legal_fpimm_begin() const { diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index f2ce1308cae..624c5d1e8f2 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -17,7 +17,7 @@ using namespace llvm; TargetLowering::TargetLowering(TargetMachine &tm) - : TM(tm), TD(TM.getTargetData()) { + : TM(tm), TD(TM.getTargetData()), ValueTypeActions(0) { assert(ISD::BUILTIN_OP_END <= 128 && "Fixed size array in TargetLowering is not large enough!"); @@ -27,9 +27,47 @@ TargetLowering::TargetLowering(TargetMachine &tm) memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*)); } +/// setValueTypeAction - Set the action for a particular value type. This +/// assumes an action has not already been set for this value type. +static void SetValueTypeAction(MVT::ValueType VT, unsigned Action, + TargetLowering &TLI, + MVT::ValueType *TransformToType, + unsigned &ValueTypeActions) { + ValueTypeActions |= Action << (VT*2); + if (Action == 1 /*promote*/) { + MVT::ValueType PromoteTo; + if (VT == MVT::f32) + PromoteTo = MVT::f64; + else { + unsigned LargerReg = VT+1; + while (!TLI.hasNativeSupportFor((MVT::ValueType)LargerReg)) { + ++LargerReg; + assert(MVT::isInteger((MVT::ValueType)LargerReg) && + "Nothing to promote to??"); + } + PromoteTo = (MVT::ValueType)LargerReg; + } + + assert(MVT::isInteger(VT) == MVT::isInteger(PromoteTo) && + MVT::isFloatingPoint(VT) == MVT::isFloatingPoint(PromoteTo) && + "Can only promote from int->int or fp->fp!"); + assert(VT < PromoteTo && "Must promote to a larger type!"); + TransformToType[VT] = PromoteTo; + } else if (Action == 2) { + assert(MVT::isInteger(VT) && VT > MVT::i8 && + "Cannot expand this type: target must support SOME integer reg!"); + // Expand to the next smaller integer type! + TransformToType[VT] = (MVT::ValueType)(VT-1); + } +} + + /// computeRegisterProperties - Once all of the register classes are added, /// this allows us to compute derived properties we expose. void TargetLowering::computeRegisterProperties() { + assert(MVT::LAST_VALUETYPE <= 16 && + "Too many value types for ValueTypeActions to hold!"); + // Everything defaults to one. for (unsigned i = 0; i != MVT::LAST_VALUETYPE; ++i) NumElementsForVT[i] = 1; @@ -44,5 +82,20 @@ void TargetLowering::computeRegisterProperties() { unsigned ExpandedReg = LargestIntReg; ++LargestIntReg; for (++ExpandedReg; MVT::isInteger((MVT::ValueType)ExpandedReg);++ExpandedReg) NumElementsForVT[ExpandedReg] = 2*NumElementsForVT[ExpandedReg-1]; -} + // Inspect all of the ValueType's possible, deciding how to process them. + for (unsigned IntReg = MVT::i1; IntReg <= MVT::i128; ++IntReg) + // If we are expanding this type, expand it! + if (getNumElements((MVT::ValueType)IntReg) != 1) + SetValueTypeAction((MVT::ValueType)IntReg, 2, *this, TransformToType, + ValueTypeActions); + else if (!hasNativeSupportFor((MVT::ValueType)IntReg)) + // Otherwise, if we don't have native support, we must promote to a + // larger type. + SetValueTypeAction((MVT::ValueType)IntReg, 1, *this, TransformToType, + ValueTypeActions); + + // If the target does not have native support for F32, promote it to F64. + if (!hasNativeSupportFor(MVT::f32)) + SetValueTypeAction(MVT::f32, 1, *this, TransformToType, ValueTypeActions); +}