diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypes.cpp | 22 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypes.h | 48 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp | 11 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp | 168 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp | 19 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp | 14 |
6 files changed, 248 insertions, 34 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index d13fefab43..cc9caf0718 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -79,6 +79,9 @@ void DAGTypeLegalizer::run() { case Expand: ExpandResult(N, i); goto NodeDone; + case FloatToInt: + FloatToIntResult(N, i); + goto NodeDone; case Scalarize: ScalarizeResult(N, i); goto NodeDone; @@ -106,6 +109,9 @@ void DAGTypeLegalizer::run() { case Expand: NeedsRevisit = ExpandOperand(N, i); break; + case FloatToInt: + NeedsRevisit = FloatToIntOperand(N, i); + break; case Scalarize: NeedsRevisit = ScalarizeOperand(N, i); break; @@ -355,6 +361,14 @@ void DAGTypeLegalizer::SetPromotedOp(SDOperand Op, SDOperand Result) { OpEntry = Result; } +void DAGTypeLegalizer::SetIntegerOp(SDOperand Op, SDOperand Result) { + AnalyzeNewNode(Result.Val); + + SDOperand &OpEntry = FloatToIntedNodes[Op]; + assert(OpEntry.Val == 0 && "Node is already converted to integer!"); + OpEntry = Result; +} + void DAGTypeLegalizer::SetScalarizedOp(SDOperand Op, SDOperand Result) { AnalyzeNewNode(Result.Val); @@ -363,7 +377,6 @@ void DAGTypeLegalizer::SetScalarizedOp(SDOperand Op, SDOperand Result) { OpEntry = Result; } - void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { std::pair<SDOperand, SDOperand> &Entry = ExpandedNodes[Op]; @@ -408,6 +421,13 @@ void DAGTypeLegalizer::SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi) { } +/// BitConvertToInteger - Convert to an integer of the same size. +SDOperand DAGTypeLegalizer::BitConvertToInteger(SDOperand Op) { + return DAG.getNode(ISD::BIT_CONVERT, + MVT::getIntegerType(MVT::getSizeInBits(Op.getValueType())), + Op); +} + SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op, MVT::ValueType DestVT) { // Create the stack frame object. diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 35e72ddeab..b8047bc2c0 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -62,6 +62,7 @@ private: Legal, // The target natively supports this type. Promote, // This type should be executed in a larger type. Expand, // This type should be split into two types of half the size. + FloatToInt, // Convert a floating point type to an integer of the same size. Scalarize, // Replace this one-element vector type with its element type. Split // This vector type should be split into smaller vectors. }; @@ -85,14 +86,20 @@ private: case TargetLowering::Promote: return Promote; case TargetLowering::Expand: - // Expand can mean 1) split integer in half 2) scalarize single-element - // vector 3) split vector in two. - if (!MVT::isVector(VT)) - return Expand; - else if (MVT::getVectorNumElements(VT) == 1) + // Expand can mean + // 1) split scalar in half, 2) convert a float to an integer, + // 3) scalarize a single-element vector, 4) split a vector in two. + if (!MVT::isVector(VT)) { + if (MVT::getSizeInBits(VT) == + MVT::getSizeInBits(TLI.getTypeToTransformTo(VT))) + return FloatToInt; + else + return Expand; + } else if (MVT::getVectorNumElements(VT) == 1) { return Scalarize; - else + } else { return Split; + } } } @@ -109,6 +116,10 @@ private: /// which operands are the expanded version of the input. DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > ExpandedNodes; + /// FloatToIntedNodes - For floating point nodes converted to integers of + /// the same size, this map indicates the converted value to use. + DenseMap<SDOperand, SDOperand> FloatToIntedNodes; + /// ScalarizedNodes - For nodes that are <1 x ty>, this map indicates the /// scalar value of type 'ty' to use. DenseMap<SDOperand, SDOperand> ScalarizedNodes; @@ -152,6 +163,7 @@ private: void RemapNode(SDOperand &N); // Common routines. + SDOperand BitConvertToInteger(SDOperand Op); SDOperand CreateStackStoreLoad(SDOperand Op, MVT::ValueType DestVT); SDOperand HandleMemIntrinsic(SDNode *N); SDOperand JoinIntegers(SDOperand Lo, SDOperand Hi); @@ -282,6 +294,28 @@ private: ISD::CondCode &CCCode); //===--------------------------------------------------------------------===// + // Float to Integer Conversion Support: LegalizeTypesFloatToInt.cpp + //===--------------------------------------------------------------------===// + + SDOperand GetIntegerOp(SDOperand Op) { + SDOperand &IntegerOp = FloatToIntedNodes[Op]; + RemapNode(IntegerOp); + assert(IntegerOp.Val && "Operand wasn't converted to integer?"); + return IntegerOp; + } + void SetIntegerOp(SDOperand Op, SDOperand Result); + + // Result Float to Integer Conversion. + void FloatToIntResult(SDNode *N, unsigned OpNo); + SDOperand FloatToIntRes_BIT_CONVERT(SDNode *N); + SDOperand FloatToIntRes_BUILD_PAIR(SDNode *N); + SDOperand FloatToIntRes_FCOPYSIGN(SDNode *N); + + // Operand Float to Integer Conversion. + bool FloatToIntOperand(SDNode *N, unsigned OpNo); + SDOperand FloatToIntOp_BIT_CONVERT(SDNode *N); + + //===--------------------------------------------------------------------===// // Scalarization Support: LegalizeTypesScalarize.cpp //===--------------------------------------------------------------------===// @@ -336,7 +370,7 @@ private: void SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi); void SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi); - // Operand Vector Scalarization: <128 x ty> -> 2 x <64 x ty>. + // Operand Vector Splitting: <128 x ty> -> 2 x <64 x ty>. bool SplitOperand(SDNode *N, unsigned OpNo); SDOperand SplitOp_BIT_CONVERT(SDNode *N); diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp index 15d25e6928..e4ae071e0c 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp @@ -260,6 +260,12 @@ void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N, Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); return; + case FloatToInt: + // Convert the integer operand instead. + SplitInteger(GetIntegerOp(InOp), Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; case Split: // Convert the split parts of the input if it was split in two. GetSplitOp(InOp, Lo, Hi); @@ -273,10 +279,7 @@ void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N, break; case Scalarize: // Convert the element instead. - InOp = DAG.getNode(ISD::BIT_CONVERT, - MVT::getIntegerType(MVT::getSizeInBits(InVT)), - GetScalarizedOp(InOp)); - SplitInteger(InOp, Lo, Hi); + SplitInteger(BitConvertToInteger(GetScalarizedOp(InOp)), Lo, Hi); Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); return; diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp new file mode 100644 index 0000000000..53f3143fca --- /dev/null +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp @@ -0,0 +1,168 @@ +//===-- LegalizeTypesFloatToInt.cpp - LegalizeTypes float to int support --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements float to integer conversion for LegalizeTypes. This +// is the act of turning a computation in an invalid floating point type into +// a computation in an integer type of the same size. For example, turning +// f32 arithmetic into operations using i32. Also known as "soft float". +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Result Float to Integer Conversion. +//===----------------------------------------------------------------------===// + +void DAGTypeLegalizer::FloatToIntResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "FloatToInt node result " << ResNo << ": "; N->dump(&DAG); + cerr << "\n"); + SDOperand R = SDOperand(); + + // FIXME: Custom lowering for float-to-int? +#if 0 + // See if the target wants to custom convert this node to an integer. + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + TargetLowering::Custom) { + // If the target wants to, allow it to lower this itself. + if (SDNode *P = TLI.FloatToIntOperationResult(N, DAG)) { + // Everything that once used N now uses P. We are guaranteed that the + // result value types of N and the result value types of P match. + ReplaceNodeWith(N, P); + return; + } + } +#endif + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "FloatToIntResult #" << ResNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to convert the result of this operator!"); + abort(); + + case ISD::BIT_CONVERT: R = FloatToIntRes_BIT_CONVERT(N); break; + case ISD::BUILD_PAIR: R = FloatToIntRes_BUILD_PAIR(N); break; + case ISD::FCOPYSIGN: R = FloatToIntRes_FCOPYSIGN(N); break; + } + + // If R is null, the sub-method took care of registering the result. + if (R.Val) + SetIntegerOp(SDOperand(N, ResNo), R); +} + +SDOperand DAGTypeLegalizer::FloatToIntRes_BIT_CONVERT(SDNode *N) { + return BitConvertToInteger(N->getOperand(0)); +} + +SDOperand DAGTypeLegalizer::FloatToIntRes_BUILD_PAIR(SDNode *N) { + // Convert the inputs to integers, and build a new pair out of them. + return DAG.getNode(ISD::BUILD_PAIR, + TLI.getTypeToTransformTo(N->getValueType(0)), + BitConvertToInteger(N->getOperand(0)), + BitConvertToInteger(N->getOperand(1))); +} + +SDOperand DAGTypeLegalizer::FloatToIntRes_FCOPYSIGN(SDNode *N) { + SDOperand LHS = GetIntegerOp(N->getOperand(0)); + SDOperand RHS = BitConvertToInteger(N->getOperand(1)); + + MVT::ValueType LVT = LHS.getValueType(); + MVT::ValueType RVT = RHS.getValueType(); + + unsigned LSize = MVT::getSizeInBits(LVT); + unsigned RSize = MVT::getSizeInBits(RVT); + + // First get the sign bit of second operand. + SDOperand SignBit = DAG.getNode(ISD::SHL, RVT, DAG.getConstant(1, RVT), + DAG.getConstant(RSize - 1, + TLI.getShiftAmountTy())); + SignBit = DAG.getNode(ISD::AND, RVT, RHS, SignBit); + + // Shift right or sign-extend it if the two operands have different types. + int SizeDiff = MVT::getSizeInBits(RVT) - MVT::getSizeInBits(LVT); + if (SizeDiff > 0) { + SignBit = DAG.getNode(ISD::SRL, RVT, SignBit, + DAG.getConstant(SizeDiff, TLI.getShiftAmountTy())); + SignBit = DAG.getNode(ISD::TRUNCATE, LVT, SignBit); + } else if (SizeDiff < 0) { + SignBit = DAG.getNode(ISD::ANY_EXTEND, LVT, SignBit); + SignBit = DAG.getNode(ISD::SHL, LVT, SignBit, + DAG.getConstant(-SizeDiff, TLI.getShiftAmountTy())); + } + + // Clear the sign bit of the first operand. + SDOperand Mask = DAG.getNode(ISD::SHL, LVT, DAG.getConstant(1, LVT), + DAG.getConstant(LSize - 1, + TLI.getShiftAmountTy())); + Mask = DAG.getNode(ISD::SUB, LVT, Mask, DAG.getConstant(1, LVT)); + LHS = DAG.getNode(ISD::AND, LVT, LHS, Mask); + + // Or the value with the sign bit. + return DAG.getNode(ISD::OR, LVT, LHS, SignBit); +} + + +//===----------------------------------------------------------------------===// +// Operand Float to Integer Conversion.. +//===----------------------------------------------------------------------===// + +bool DAGTypeLegalizer::FloatToIntOperand(SDNode *N, unsigned OpNo) { + DEBUG(cerr << "FloatToInt node operand " << OpNo << ": "; N->dump(&DAG); + cerr << "\n"); + SDOperand Res(0, 0); + + // FIXME: Custom lowering for float-to-int? +#if 0 + if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) + == TargetLowering::Custom) + Res = TLI.LowerOperation(SDOperand(N, 0), DAG); +#endif + + if (Res.Val == 0) { + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "FloatToIntOperand Op #" << OpNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to convert this operator's operand!"); + abort(); + + case ISD::BIT_CONVERT: Res = FloatToIntOp_BIT_CONVERT(N); break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.Val) return false; + + // If the result is N, the sub-method updated N in place. Check to see if any + // operands are new, and if so, mark them. + if (Res.Val == N) { + // Mark N as new and remark N and its operands. This allows us to correctly + // revisit N if it needs another step of promotion and allows us to visit + // any new operands to N. + ReanalyzeNode(N); + return true; + } + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDOperand(N, 0), Res); + return false; +} + +SDOperand DAGTypeLegalizer::FloatToIntOp_BIT_CONVERT(SDNode *N) { + return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), + GetIntegerOp(N->getOperand(0))); +} diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp index 1a0dfe755d..eef7a83a10 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp @@ -234,25 +234,20 @@ SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) { break; case Expand: break; + case FloatToInt: + // Promote the integer operand by hand. + return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetIntegerOp(InOp)); case Scalarize: // Convert the element to an integer and promote it by hand. - InOp = DAG.getNode(ISD::BIT_CONVERT, - MVT::getIntegerType(MVT::getSizeInBits(InVT)), - GetScalarizedOp(InOp)); - InOp = DAG.getNode(ISD::ANY_EXTEND, - MVT::getIntegerType(MVT::getSizeInBits(OutVT)), InOp); - return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp); + return DAG.getNode(ISD::ANY_EXTEND, OutVT, + BitConvertToInteger(GetScalarizedOp(InOp))); case Split: // For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the split // pieces of the input into integers and reassemble in the final type. SDOperand Lo, Hi; GetSplitOp(N->getOperand(0), Lo, Hi); - - unsigned LoBits = MVT::getSizeInBits(Lo.getValueType()); - Lo = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(LoBits), Lo); - - unsigned HiBits = MVT::getSizeInBits(Hi.getValueType()); - Hi = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(HiBits), Hi); + Lo = BitConvertToInteger(Lo); + Hi = BitConvertToInteger(Hi); if (TLI.isBigEndian()) std::swap(Lo, Hi); diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp index 2e76cebf16..4a8c47401e 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp @@ -263,6 +263,7 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, default: assert(false && "Unknown type action!"); case Legal: + case FloatToInt: case Promote: case Scalarize: break; @@ -289,15 +290,12 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, } // In the general case, convert the input to an integer and split it by hand. - InVT = MVT::getIntegerType(MVT::getSizeInBits(InVT)); - InOp = DAG.getNode(ISD::BIT_CONVERT, InVT, InOp); - MVT::ValueType LoIntVT = MVT::getIntegerType(MVT::getSizeInBits(LoVT)); MVT::ValueType HiIntVT = MVT::getIntegerType(MVT::getSizeInBits(HiVT)); if (TLI.isBigEndian()) std::swap(LoIntVT, HiIntVT); - SplitInteger(InOp, LoIntVT, HiIntVT, Lo, Hi); + SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi); if (TLI.isBigEndian()) std::swap(Lo, Hi); @@ -444,12 +442,8 @@ SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) { // split pieces into integers and reassemble. SDOperand Lo, Hi; GetSplitOp(N->getOperand(0), Lo, Hi); - - unsigned LoBits = MVT::getSizeInBits(Lo.getValueType()); - Lo = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(LoBits), Lo); - - unsigned HiBits = MVT::getSizeInBits(Hi.getValueType()); - Hi = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(HiBits), Hi); + Lo = BitConvertToInteger(Lo); + Hi = BitConvertToInteger(Hi); if (TLI.isBigEndian()) std::swap(Lo, Hi); |