aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/RuntimeLibcalls.h2
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h8
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp204
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypes.h11
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp7
-rw-r--r--lib/CodeGen/SelectionDAG/TargetLowering.cpp2
6 files changed, 221 insertions, 13 deletions
diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h
index 92a0b78886..0138b0c484 100644
--- a/include/llvm/CodeGen/RuntimeLibcalls.h
+++ b/include/llvm/CodeGen/RuntimeLibcalls.h
@@ -99,6 +99,7 @@ namespace RTLIB {
FPTOSINT_F64_I128,
FPTOSINT_F80_I64,
FPTOSINT_F80_I128,
+ FPTOSINT_PPCF128_I32,
FPTOSINT_PPCF128_I64,
FPTOSINT_PPCF128_I128,
FPTOUINT_F32_I32,
@@ -110,6 +111,7 @@ namespace RTLIB {
FPTOUINT_F80_I32,
FPTOUINT_F80_I64,
FPTOUINT_F80_I128,
+ FPTOUINT_PPCF128_I32,
FPTOUINT_PPCF128_I64,
FPTOUINT_PPCF128_I128,
SINTTOFP_I32_F32,
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 2e27455813..f56863cd6e 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -193,16 +193,16 @@ namespace ISD {
CALL,
// EXTRACT_ELEMENT - This is used to get the lower or upper (determined by
- // a Constant, which is required to be operand #1) half of the integer value
- // specified as operand #0. This is only for use before legalization, for
- // values that will be broken into multiple registers.
+ // a Constant, which is required to be operand #1) half of the integer or
+ // float value specified as operand #0. This is only for use before
+ // legalization, for values that will be broken into multiple registers.
EXTRACT_ELEMENT,
// BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways. Given
// two values of the same integer value type, this produces a value twice as
// big. Like EXTRACT_ELEMENT, this can only be used before legalization.
BUILD_PAIR,
-
+
// MERGE_VALUES - This node takes multiple discrete operands and returns
// them all as its individual results. This nodes has exactly the same
// number of inputs and outputs, and is only valid before legalization.
diff --git a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index d99a9bd6df..be1d45502d 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -118,7 +118,7 @@ SDOperand DAGTypeLegalizer::SoftenFloatRes_FADD(SDNode *N) {
RTLIB::ADD_F64,
RTLIB::ADD_F80,
RTLIB::ADD_PPCF128),
- NVT, Ops, 2, false/*sign irrelevant*/);
+ NVT, Ops, 2, false);
}
SDOperand DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN(SDNode *N) {
@@ -169,7 +169,7 @@ SDOperand DAGTypeLegalizer::SoftenFloatRes_FMUL(SDNode *N) {
RTLIB::MUL_F64,
RTLIB::MUL_F80,
RTLIB::MUL_PPCF128),
- NVT, Ops, 2, false/*sign irrelevant*/);
+ NVT, Ops, 2, false);
}
SDOperand DAGTypeLegalizer::SoftenFloatRes_FSUB(SDNode *N) {
@@ -181,7 +181,7 @@ SDOperand DAGTypeLegalizer::SoftenFloatRes_FSUB(SDNode *N) {
RTLIB::SUB_F64,
RTLIB::SUB_F80,
RTLIB::SUB_PPCF128),
- NVT, Ops, 2, false/*sign irrelevant*/);
+ NVT, Ops, 2, false);
}
SDOperand DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) {
@@ -547,7 +547,14 @@ void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) {
case ISD::EXTRACT_ELEMENT: ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break;
case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break;
- case ISD::LOAD: ExpandFloatRes_LOAD(N, Lo, Hi); break;
+ case ISD::ConstantFP: ExpandFloatRes_ConstantFP(N, Lo, Hi); break;
+ case ISD::FADD: ExpandFloatRes_FADD(N, Lo, Hi); break;
+ case ISD::FDIV: ExpandFloatRes_FDIV(N, Lo, Hi); break;
+ case ISD::FMUL: ExpandFloatRes_FMUL(N, Lo, Hi); break;
+ case ISD::FSUB: ExpandFloatRes_FSUB(N, Lo, Hi); break;
+ case ISD::LOAD: ExpandFloatRes_LOAD(N, Lo, Hi); break;
+ case ISD::SINT_TO_FP:
+ case ISD::UINT_TO_FP: ExpandFloatRes_XINT_TO_FP(N, Lo, Hi); break;
}
// If Lo/Hi is null, the sub-method took care of registering results etc.
@@ -555,6 +562,74 @@ void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) {
SetExpandedFloat(SDOperand(N, ResNo), Lo, Hi);
}
+void DAGTypeLegalizer::ExpandFloatRes_ConstantFP(SDNode *N, SDOperand &Lo,
+ SDOperand &Hi) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ assert(NVT.getSizeInBits() == integerPartWidth &&
+ "Do not know how to expand this float constant!");
+ APInt C = cast<ConstantFPSDNode>(N)->getValueAPF().convertToAPInt();
+ Lo = DAG.getConstantFP(APFloat(APInt(integerPartWidth, 1,
+ &C.getRawData()[1])), NVT);
+ Hi = DAG.getConstantFP(APFloat(APInt(integerPartWidth, 1,
+ &C.getRawData()[0])), NVT);
+}
+
+void DAGTypeLegalizer::ExpandFloatRes_FADD(SDNode *N, SDOperand &Lo,
+ SDOperand &Hi) {
+ SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
+ SDOperand Call = MakeLibCall(GetFPLibCall(N->getValueType(0),
+ RTLIB::ADD_F32,
+ RTLIB::ADD_F64,
+ RTLIB::ADD_F80,
+ RTLIB::ADD_PPCF128),
+ N->getValueType(0), Ops, 2,
+ false);
+ assert(Call.Val->getOpcode() == ISD::BUILD_PAIR && "Call lowered wrongly!");
+ Lo = Call.getOperand(0); Hi = Call.getOperand(1);
+}
+
+void DAGTypeLegalizer::ExpandFloatRes_FDIV(SDNode *N, SDOperand &Lo,
+ SDOperand &Hi) {
+ SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
+ SDOperand Call = MakeLibCall(GetFPLibCall(N->getValueType(0),
+ RTLIB::DIV_F32,
+ RTLIB::DIV_F64,
+ RTLIB::DIV_F80,
+ RTLIB::DIV_PPCF128),
+ N->getValueType(0), Ops, 2,
+ false);
+ assert(Call.Val->getOpcode() == ISD::BUILD_PAIR && "Call lowered wrongly!");
+ Lo = Call.getOperand(0); Hi = Call.getOperand(1);
+}
+
+void DAGTypeLegalizer::ExpandFloatRes_FMUL(SDNode *N, SDOperand &Lo,
+ SDOperand &Hi) {
+ SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
+ SDOperand Call = MakeLibCall(GetFPLibCall(N->getValueType(0),
+ RTLIB::MUL_F32,
+ RTLIB::MUL_F64,
+ RTLIB::MUL_F80,
+ RTLIB::MUL_PPCF128),
+ N->getValueType(0), Ops, 2,
+ false);
+ assert(Call.Val->getOpcode() == ISD::BUILD_PAIR && "Call lowered wrongly!");
+ Lo = Call.getOperand(0); Hi = Call.getOperand(1);
+}
+
+void DAGTypeLegalizer::ExpandFloatRes_FSUB(SDNode *N, SDOperand &Lo,
+ SDOperand &Hi) {
+ SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
+ SDOperand Call = MakeLibCall(GetFPLibCall(N->getValueType(0),
+ RTLIB::SUB_F32,
+ RTLIB::SUB_F64,
+ RTLIB::SUB_F80,
+ RTLIB::SUB_PPCF128),
+ N->getValueType(0), Ops, 2,
+ false);
+ assert(Call.Val->getOpcode() == ISD::BUILD_PAIR && "Call lowered wrongly!");
+ Lo = Call.getOperand(0); Hi = Call.getOperand(1);
+}
+
void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDOperand &Lo,
SDOperand &Hi) {
if (ISD::isNormalLoad(N)) {
@@ -587,6 +662,71 @@ void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDOperand &Lo,
ReplaceValueWith(SDOperand(LD, 1), Chain);
}
+void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDOperand &Lo,
+ SDOperand &Hi) {
+ assert(N->getValueType(0) == MVT::ppcf128 && "Unsupported XINT_TO_FP!");
+ MVT VT = N->getValueType(0);
+ MVT NVT = TLI.getTypeToTransformTo(VT);
+ SDOperand Src = N->getOperand(0);
+ MVT SrcVT = Src.getValueType();
+
+ // First do an SINT_TO_FP, whether the original was signed or unsigned.
+ if (SrcVT.bitsLE(MVT::i32)) {
+ // The integer can be represented exactly in an f64.
+ Src = DAG.getNode(ISD::SIGN_EXTEND, MVT::i32, Src);
+ Lo = DAG.getConstantFP(APFloat(APInt(NVT.getSizeInBits(), 0)), NVT);
+ Hi = DAG.getNode(ISD::SINT_TO_FP, NVT, Src);
+ } else {
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ if (SrcVT.bitsLE(MVT::i64)) {
+ Src = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Src);
+ LC = RTLIB::SINTTOFP_I64_PPCF128;
+ } else if (SrcVT.bitsLE(MVT::i128)) {
+ Src = DAG.getNode(ISD::SIGN_EXTEND, MVT::i128, Src);
+ LC = RTLIB::SINTTOFP_I128_PPCF128;
+ }
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!");
+
+ Hi = MakeLibCall(LC, VT, &Src, 1, true);
+ assert(Hi.Val->getOpcode() == ISD::BUILD_PAIR && "Call lowered wrongly!");
+ Lo = Hi.getOperand(0); Hi = Hi.getOperand(1);
+ }
+
+ if (N->getOpcode() == ISD::SINT_TO_FP)
+ return;
+
+ // Unsigned - fix up the SINT_TO_FP value just calculated.
+ Hi = DAG.getNode(ISD::BUILD_PAIR, VT, Lo, Hi);
+ SrcVT = Src.getValueType();
+
+ // x>=0 ? (ppcf128)(iN)x : (ppcf128)(iN)x + 2^N; N=32,64,128.
+ static const uint64_t TwoE32[] = { 0x41f0000000000000LL, 0 };
+ static const uint64_t TwoE64[] = { 0x43f0000000000000LL, 0 };
+ static const uint64_t TwoE128[] = { 0x47f0000000000000LL, 0 };
+ const uint64_t *Parts = 0;
+
+ switch (SrcVT.getSimpleVT()) {
+ default:
+ assert(false && "Unsupported UINT_TO_FP!");
+ case MVT::i32:
+ Parts = TwoE32;
+ case MVT::i64:
+ Parts = TwoE64;
+ case MVT::i128:
+ Parts = TwoE128;
+ }
+
+ Lo = DAG.getNode(ISD::FADD, VT, Hi,
+ DAG.getConstantFP(APFloat(APInt(128, 2, Parts)),
+ MVT::ppcf128));
+ Lo = DAG.getNode(ISD::SELECT_CC, VT, Src, DAG.getConstant(0, SrcVT), Lo, Hi,
+ DAG.getCondCode(ISD::SETLT));
+ Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, NVT, Lo,
+ DAG.getConstant(1, TLI.getPointerTy()));
+ Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, NVT, Lo,
+ DAG.getConstant(0, TLI.getPointerTy()));
+}
+
//===----------------------------------------------------------------------===//
// Float Operand Expansion
@@ -622,6 +762,10 @@ bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) {
case ISD::SELECT_CC: Res = ExpandFloatOp_BR_CC(N); break;
case ISD::SETCC: Res = ExpandFloatOp_BR_CC(N); break;
+ case ISD::FP_ROUND: Res = ExpandFloatOp_FP_ROUND(N); break;
+ case ISD::FP_TO_SINT: Res = ExpandFloatOp_FP_TO_SINT(N); break;
+ case ISD::FP_TO_UINT: Res = ExpandFloatOp_FP_TO_UINT(N); break;
+
case ISD::STORE:
Res = ExpandFloatOp_STORE(cast<StoreSDNode>(N), OpNo);
break;
@@ -728,6 +872,58 @@ SDOperand DAGTypeLegalizer::ExpandFloatOp_SETCC(SDNode *N) {
DAG.getCondCode(CCCode));
}
+SDOperand DAGTypeLegalizer::ExpandFloatOp_FP_TO_UINT(SDNode *N) {
+ assert(N->getOperand(0).getValueType() == MVT::ppcf128 &&
+ "Unsupported FP_TO_UINT!");
+
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ switch (N->getValueType(0).getSimpleVT()) {
+ default:
+ assert(false && "Unsupported FP_TO_UINT!");
+ case MVT::i32:
+ LC = RTLIB::FPTOUINT_PPCF128_I32;
+ break;
+ case MVT::i64:
+ LC = RTLIB::FPTOUINT_PPCF128_I64;
+ break;
+ case MVT::i128:
+ LC = RTLIB::FPTOUINT_PPCF128_I128;
+ break;
+ }
+
+ return MakeLibCall(LC, N->getValueType(0), &N->getOperand(0), 1, false);
+}
+
+SDOperand DAGTypeLegalizer::ExpandFloatOp_FP_TO_SINT(SDNode *N) {
+ assert(N->getOperand(0).getValueType() == MVT::ppcf128 &&
+ "Unsupported FP_TO_SINT!");
+
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ switch (N->getValueType(0).getSimpleVT()) {
+ default:
+ assert(false && "Unsupported FP_TO_SINT!");
+ case MVT::i32:
+ LC = RTLIB::FPTOSINT_PPCF128_I32;
+ case MVT::i64:
+ LC = RTLIB::FPTOSINT_PPCF128_I64;
+ break;
+ case MVT::i128:
+ LC = RTLIB::FPTOSINT_PPCF128_I64;
+ break;
+ }
+
+ return MakeLibCall(LC, N->getValueType(0), &N->getOperand(0), 1, false);
+}
+
+SDOperand DAGTypeLegalizer::ExpandFloatOp_FP_ROUND(SDNode *N) {
+ assert(N->getOperand(0).getValueType() == MVT::ppcf128 &&
+ "Logic only correct for ppcf128!");
+ SDOperand Lo, Hi;
+ GetExpandedFloat(N->getOperand(0), Lo, Hi);
+ // Round it the rest of the way (e.g. to f32) if needed.
+ return DAG.getNode(ISD::FP_ROUND, N->getValueType(0), Hi, N->getOperand(1));
+}
+
SDOperand DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) {
if (ISD::isNormalStore(N))
return ExpandOp_NormalStore(N, OpNo);
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index ea7ac8f26b..add3dcdf1b 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -354,11 +354,20 @@ private:
// Float Result Expansion.
void ExpandFloatResult(SDNode *N, unsigned ResNo);
- void ExpandFloatRes_LOAD(SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandFloatRes_ConstantFP(SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandFloatRes_FADD (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandFloatRes_FDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandFloatRes_FMUL (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandFloatRes_FSUB (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandFloatRes_LOAD (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandFloatRes_XINT_TO_FP(SDNode *N, SDOperand &Lo, SDOperand &Hi);
// Float Operand Expansion.
bool ExpandFloatOperand(SDNode *N, unsigned OperandNo);
SDOperand ExpandFloatOp_BR_CC(SDNode *N);
+ SDOperand ExpandFloatOp_FP_ROUND(SDNode *N);
+ SDOperand ExpandFloatOp_FP_TO_SINT(SDNode *N);
+ SDOperand ExpandFloatOp_FP_TO_UINT(SDNode *N);
SDOperand ExpandFloatOp_SELECT_CC(SDNode *N);
SDOperand ExpandFloatOp_SETCC(SDNode *N);
SDOperand ExpandFloatOp_STORE(SDNode *N, unsigned OpNo);
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 78281aa632..fdff418a61 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2244,10 +2244,9 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT VT,
break;
case ISD::EXTRACT_ELEMENT:
assert(N2C && (unsigned)N2C->getValue() < 2 && "Bad EXTRACT_ELEMENT!");
- assert(!N1.getValueType().isVector() &&
- N1.getValueType().isInteger() &&
- !VT.isVector() && VT.isInteger() &&
- "EXTRACT_ELEMENT only applies to integers!");
+ assert(!N1.getValueType().isVector() && !VT.isVector() &&
+ (N1.getValueType().isInteger() == VT.isInteger()) &&
+ "Wrong types for EXTRACT_ELEMENT!");
// EXTRACT_ELEMENT of BUILD_PAIR is often formed while legalize is expanding
// 64-bit integers into 32-bit parts. Instead of building the extract of
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index c99319338e..ae9b917f1b 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -97,6 +97,7 @@ static void InitLibcallNames(const char **Names) {
Names[RTLIB::FPTOSINT_F64_I128] = "__fixdfti";
Names[RTLIB::FPTOSINT_F80_I64] = "__fixxfdi";
Names[RTLIB::FPTOSINT_F80_I128] = "__fixxfti";
+ Names[RTLIB::FPTOSINT_PPCF128_I32] = "__fixtfsi";
Names[RTLIB::FPTOSINT_PPCF128_I64] = "__fixtfdi";
Names[RTLIB::FPTOSINT_PPCF128_I128] = "__fixtfti";
Names[RTLIB::FPTOUINT_F32_I32] = "__fixunssfsi";
@@ -108,6 +109,7 @@ static void InitLibcallNames(const char **Names) {
Names[RTLIB::FPTOUINT_F80_I32] = "__fixunsxfsi";
Names[RTLIB::FPTOUINT_F80_I64] = "__fixunsxfdi";
Names[RTLIB::FPTOUINT_F80_I128] = "__fixunsxfti";
+ Names[RTLIB::FPTOUINT_PPCF128_I32] = "__fixunstfsi";
Names[RTLIB::FPTOUINT_PPCF128_I64] = "__fixunstfdi";
Names[RTLIB::FPTOUINT_PPCF128_I128] = "__fixunstfti";
Names[RTLIB::SINTTOFP_I32_F32] = "__floatsisf";