case Expand:
ExpandResult(N, i);
goto NodeDone;
+ case FloatToInt:
+ FloatToIntResult(N, i);
+ goto NodeDone;
case Scalarize:
ScalarizeResult(N, i);
goto NodeDone;
case Expand:
NeedsRevisit = ExpandOperand(N, i);
break;
+ case FloatToInt:
+ NeedsRevisit = FloatToIntOperand(N, i);
+ break;
case Scalarize:
NeedsRevisit = ScalarizeOperand(N, i);
break;
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);
OpEntry = Result;
}
-
void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo,
SDOperand &Hi) {
std::pair<SDOperand, SDOperand> &Entry = ExpandedNodes[Op];
}
+/// 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.
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.
};
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;
+ }
}
}
/// 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;
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);
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
//===--------------------------------------------------------------------===//
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);
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);
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;
--- /dev/null
+//===-- 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)));
+}
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);
default:
assert(false && "Unknown type action!");
case Legal:
+ case FloatToInt:
case Promote:
case Scalarize:
break;
}
// 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);
// 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);