diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 9388df1e6dd..ccda26f2cee 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -174,9 +174,14 @@ public: return getConstant(Val, VT, true); } SDOperand getConstantFP(double Val, MVT::ValueType VT, bool isTarget = false); + SDOperand getConstantFP(const APFloat& Val, MVT::ValueType VT, + bool isTarget = false); SDOperand getTargetConstantFP(double Val, MVT::ValueType VT) { return getConstantFP(Val, VT, true); } + SDOperand getTargetConstantFP(const APFloat& Val, MVT::ValueType VT) { + return getConstantFP(Val, VT, true); + } SDOperand getGlobalAddress(const GlobalValue *GV, MVT::ValueType VT, int offset = 0, bool isTargetGA = false); SDOperand getTargetGlobalAddress(const GlobalValue *GV, MVT::ValueType VT, diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index fed77a53ce6..d2c2fa28841 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1182,6 +1182,8 @@ public: } bool isExactlyValue(const APFloat& V) const; + bool isValueValidForType(MVT::ValueType VT, const APFloat& Val); + static bool classof(const ConstantFPSDNode *) { return true; } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::ConstantFP || diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 4aa5afbcf9a..86b4daadad1 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -218,12 +218,20 @@ class ConstantFP : public Constant { ConstantFP(const ConstantFP &); // DO NOT IMPLEMENT protected: ConstantFP(const Type *Ty, double V); + ConstantFP(const Type *Ty, const APFloat& V); public: /// get() - Static factory methods - Return objects of the specified value static ConstantFP *get(const Type *Ty, double V); + static ConstantFP *get(const Type *Ty, const APFloat& V); /// isValueValidForType - return true if Ty is big enough to represent V. - static bool isValueValidForType(const Type *Ty, double V); + static bool isValueValidForType(const Type *Ty, const APFloat& V); + static bool isValueValidForType(const Type *Ty, double V) { + if (Ty == Type::FloatTy) + return isValueValidForType(Ty, APFloat((float)V)); + else + return isValueValidForType(Ty, APFloat(V)); + } inline double getValue() const { if (&Val.getSemantics() == &APFloat::IEEEdouble) return Val.convertToDouble(); @@ -232,6 +240,7 @@ public: else assert(0); } + inline const APFloat& getValueAPF() const { return Val; } /// isNullValue - Return true if this is the value that would be returned by /// getNullValue. Don't depend on == for doubles to tell us it's zero, it @@ -242,8 +251,15 @@ public: /// it returns true for things that are clearly not equal, like -0.0 and 0.0. /// As such, this method can be used to do an exact bit-for-bit comparison of /// two floating point values. - bool isExactlyValue(double V) const; - + bool isExactlyValue(const APFloat& V) const; + bool isExactlyValue(double V) const { + if (&Val.getSemantics() == &APFloat::IEEEdouble) + return isExactlyValue(APFloat(V)); + else if (&Val.getSemantics() == &APFloat::IEEEsingle) + return isExactlyValue(APFloat((float)V)); + else + assert(0); + } /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ConstantFP *) { return true; } static bool classof(const Value *V) { diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index ed97a93b44b..f2f5bbaf233 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -24,6 +24,7 @@ #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/ADT/APFloat.h" #include #include @@ -220,7 +221,7 @@ public: unsigned &NumIntermediates, MVT::ValueType &RegisterVT) const; - typedef std::vector::const_iterator legal_fpimm_iterator; + typedef std::vector::const_iterator legal_fpimm_iterator; legal_fpimm_iterator legal_fpimm_begin() const { return LegalFPImmediates.begin(); } @@ -781,8 +782,18 @@ protected: /// addLegalFPImmediate - Indicate that this target can instruction select /// the specified FP immediate natively. - void addLegalFPImmediate(double Imm) { + void addLegalFPImmediate(const APFloat& Imm) { + // Incoming constants are expected to be double. We also add + // the float version. It is expected that all constants are exactly + // representable as floats. + assert(&Imm.getSemantics() == &APFloat::IEEEdouble); + APFloat Immf = APFloat(Imm); + // Rounding mode is not supposed to matter here... + if (Immf.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven) != + APFloat::opOK) + assert(0); LegalFPImmediates.push_back(Imm); + LegalFPImmediates.push_back(Immf); } /// setTargetDAGCombine - Targets should invoke this method for each target @@ -1118,7 +1129,7 @@ private: ValueTypeActionImpl ValueTypeActions; - std::vector LegalFPImmediates; + std::vector LegalFPImmediates; std::vector > AvailableRegClasses; diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index c7803caa839..265209c6820 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -487,15 +487,15 @@ static SDOperand ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, MVT::ValueType VT = CFP->getValueType(0); bool isDouble = VT == MVT::f64; ConstantFP *LLVMC = ConstantFP::get(isDouble ? Type::DoubleTy : - Type::FloatTy, CFP->getValue()); + Type::FloatTy, CFP->getValueAPF()); if (!UseCP) { - double Val = LLVMC->getValue(); + const APFloat& Val = LLVMC->getValueAPF(); return isDouble - ? DAG.getConstant(DoubleToBits(Val), MVT::i64) - : DAG.getConstant(FloatToBits(Val), MVT::i32); + ? DAG.getConstant(DoubleToBits(Val.convertToDouble()), MVT::i64) + : DAG.getConstant(FloatToBits(Val.convertToFloat()), MVT::i32); } - if (isDouble && CFP->isExactlyValue((float)CFP->getValue()) && + if (isDouble && CFP->isValueValidForType(MVT::f32, CFP->getValueAPF()) && // Only do this if the target has a native EXTLOAD instruction from f32. TLI.isLoadXLegal(ISD::EXTLOAD, MVT::f32)) { LLVMC = cast(ConstantExpr::getFPTrunc(LLVMC,Type::FloatTy)); @@ -1017,7 +1017,8 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { // If this is a legal constant, turn it into a TargetConstantFP node. if (isLegal) { - Result = DAG.getTargetConstantFP(CFP->getValue(), CFP->getValueType(0)); + Result = DAG.getTargetConstantFP(CFP->getValueAPF(), + CFP->getValueType(0)); break; } @@ -1942,10 +1943,12 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { // together. if (ConstantFPSDNode *CFP = dyn_cast(ST->getValue())) { if (CFP->getValueType(0) == MVT::f32) { - Tmp3 = DAG.getConstant(FloatToBits(CFP->getValue()), MVT::i32); + Tmp3 = DAG.getConstant(FloatToBits(CFP->getValueAPF(). + convertToFloat()), MVT::i32); } else { assert(CFP->getValueType(0) == MVT::f64 && "Unknown FP type!"); - Tmp3 = DAG.getConstant(DoubleToBits(CFP->getValue()), MVT::i64); + Tmp3 = DAG.getConstant(DoubleToBits(CFP->getValueAPF(). + convertToDouble()), MVT::i64); } Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(), SVOffset, isVolatile, Alignment); @@ -4212,7 +4215,7 @@ SDOperand SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { for (unsigned i = 0, e = NumElems; i != e; ++i) { if (ConstantFPSDNode *V = dyn_cast(Node->getOperand(i))) { - CV.push_back(ConstantFP::get(OpNTy, V->getValue())); + CV.push_back(ConstantFP::get(OpNTy, V->getValueAPF())); } else if (ConstantSDNode *V = dyn_cast(Node->getOperand(i))) { CV.push_back(ConstantInt::get(OpNTy, V->getValue())); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 055834b5039..d544e8e37c8 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -52,6 +52,32 @@ bool ConstantFPSDNode::isExactlyValue(const APFloat& V) const { return Value.bitwiseIsEqual(V); } +bool ConstantFPSDNode::isValueValidForType(MVT::ValueType VT, + const APFloat& Val) { + // convert modifies in place, so make a copy. + APFloat Val2 = APFloat(Val); + switch (VT) { + default: + return false; // These can't be represented as floating point! + + // FIXME rounding mode needs to be more flexible + case MVT::f32: + return &Val2.getSemantics() == &APFloat::IEEEsingle || + Val2.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven) == + APFloat::opOK; + case MVT::f64: + return &Val2.getSemantics() == &APFloat::IEEEsingle || + &Val2.getSemantics() == &APFloat::IEEEdouble || + Val2.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven) == + APFloat::opOK; + // TODO: Figure out how to test if we can use a shorter type instead! + case MVT::f80: + case MVT::f128: + case MVT::ppcf128: + return true; + } +} + //===----------------------------------------------------------------------===// // ISD Namespace //===----------------------------------------------------------------------===// @@ -669,18 +695,20 @@ SDOperand SelectionDAG::getConstant(uint64_t Val, MVT::ValueType VT, bool isT) { return SDOperand(N, 0); } -SDOperand SelectionDAG::getConstantFP(double Val, MVT::ValueType VT, +SDOperand SelectionDAG::getConstantFP(const APFloat& V, MVT::ValueType VT, bool isTarget) { assert(MVT::isFloatingPoint(VT) && "Cannot create integer FP constant!"); + MVT::ValueType EltVT = MVT::isVector(VT) ? MVT::getVectorElementType(VT) : VT; - if (EltVT == MVT::f32) - Val = (float)Val; // Mask out extra precision. + bool isDouble = (EltVT == MVT::f64); + double Val = isDouble ? V.convertToDouble() : (double)V.convertToFloat(); // Do the map lookup using the actual bit pattern for the floating point // value, so that we don't have problems with 0.0 comparing equal to -0.0, and // we don't have issues with SNANs. unsigned Opc = isTarget ? ISD::TargetConstantFP : ISD::ConstantFP; + // ?? Should we store float/double/longdouble separately in ID? FoldingSetNodeID ID; AddNodeIDNode(ID, Opc, getVTList(EltVT), 0, 0); ID.AddDouble(Val); @@ -704,6 +732,16 @@ SDOperand SelectionDAG::getConstantFP(double Val, MVT::ValueType VT, return Result; } +SDOperand SelectionDAG::getConstantFP(double Val, MVT::ValueType VT, + bool isTarget) { + MVT::ValueType EltVT = + MVT::isVector(VT) ? MVT::getVectorElementType(VT) : VT; + if (EltVT==MVT::f32) + return getConstantFP(APFloat((float)Val), VT, isTarget); + else + return getConstantFP(APFloat(Val), VT, isTarget); +} + SDOperand SelectionDAG::getGlobalAddress(const GlobalValue *GV, MVT::ValueType VT, int Offset, bool isTargetGA) { diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index d2e52adb170..47ec9eeaea5 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -1617,7 +1617,7 @@ APFloat::APFloat(double d) { sign = mysign; category = fcNormal; exponent = myexponent - 1023; - *significandParts() = mysignificand | 0x100000000000000LL; + *significandParts() = mysignificand | 0x10000000000000LL; } } diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index adbf322dade..faeb7918248 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -142,8 +142,8 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) setOperationAction(ISD::ConstantFP, MVT::f64, Expand); setOperationAction(ISD::ConstantFP, MVT::f32, Expand); - addLegalFPImmediate(+0.0); //F31 - addLegalFPImmediate(-0.0); //-F31 + addLegalFPImmediate(APFloat(+0.0)); //F31 + addLegalFPImmediate(APFloat(-0.0)); //-F31 setJumpBufSize(272); setJumpBufAlignment(16); diff --git a/lib/Target/IA64/IA64ISelLowering.cpp b/lib/Target/IA64/IA64ISelLowering.cpp index b9508a9cb35..8f62c1f4191 100644 --- a/lib/Target/IA64/IA64ISelLowering.cpp +++ b/lib/Target/IA64/IA64ISelLowering.cpp @@ -121,8 +121,8 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM) computeRegisterProperties(); setOperationAction(ISD::ConstantFP, MVT::f64, Expand); - addLegalFPImmediate(+0.0); - addLegalFPImmediate(+1.0); + addLegalFPImmediate(APFloat(+0.0)); + addLegalFPImmediate(APFloat(+1.0)); } const char *IA64TargetLowering::getTargetNodeName(unsigned Opcode) const { diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 7ebac836dd7..99fc9bae638 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -296,7 +296,7 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) // cases we handle. setOperationAction(ISD::ConstantFP, MVT::f64, Expand); setOperationAction(ISD::ConstantFP, MVT::f32, Expand); - addLegalFPImmediate(+0.0); // xorps / xorpd + addLegalFPImmediate(APFloat(+0.0)); // xorps / xorpd // Conversions to long double (in X87) go through memory. setConvertAction(MVT::f32, MVT::f80, Expand); @@ -327,10 +327,10 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) setOperationAction(ISD::ConstantFP, MVT::f64, Expand); setOperationAction(ISD::ConstantFP, MVT::f32, Expand); - addLegalFPImmediate(+0.0); // FLD0 - addLegalFPImmediate(+1.0); // FLD1 - addLegalFPImmediate(-0.0); // FLD0/FCHS - addLegalFPImmediate(-1.0); // FLD1/FCHS + addLegalFPImmediate(APFloat(+0.0)); // FLD0 + addLegalFPImmediate(APFloat(+1.0)); // FLD1 + addLegalFPImmediate(APFloat(-0.0)); // FLD0/FCHS + addLegalFPImmediate(APFloat(-1.0)); // FLD1/FCHS } // Long double always uses X87. diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 04689e4c98a..8e3d946ec47 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -240,15 +240,24 @@ ConstantInt *ConstantInt::get(const APInt& V) { ConstantFP::ConstantFP(const Type *Ty, double V) - : Constant(Ty, ConstantFPVal, 0, 0), Val(APFloat(V)) { + : Constant(Ty, ConstantFPVal, 0, 0), + Val(Ty==Type::FloatTy ? APFloat((float)V) : APFloat(V)) { +} +ConstantFP::ConstantFP(const Type *Ty, const APFloat& V) + : Constant(Ty, ConstantFPVal, 0, 0), Val(V) { + // temporary + if (Ty==Type::FloatTy) + assert(&V.getSemantics()==&APFloat::IEEEsingle); + else + assert(&V.getSemantics()==&APFloat::IEEEdouble); } bool ConstantFP::isNullValue() const { return Val.isZero() && !Val.isNegative(); } -bool ConstantFP::isExactlyValue(double V) const { - return Val.bitwiseIsEqual(APFloat(V)); +bool ConstantFP::isExactlyValue(const APFloat& V) const { + return Val.bitwiseIsEqual(V); } namespace { @@ -289,14 +298,14 @@ ConstantFP *ConstantFP::get(const Type *Ty, double V) { DenseMapAPFloatKeyInfo::KeyTy Key(APFloat((float)V)); ConstantFP *&Slot = (*FPConstants)[Key]; if (Slot) return Slot; - return Slot = new ConstantFP(Ty, (float)V); + return Slot = new ConstantFP(Ty, APFloat((float)V)); } else if (Ty == Type::DoubleTy) { // Without the redundant cast, the following is taken to be // a function declaration. What a language. DenseMapAPFloatKeyInfo::KeyTy Key(APFloat((double)V)); ConstantFP *&Slot = (*FPConstants)[Key]; if (Slot) return Slot; - return Slot = new ConstantFP(Ty, V); + return Slot = new ConstantFP(Ty, APFloat(V)); } else if (Ty == Type::X86_FP80Ty || Ty == Type::PPC_FP128Ty || Ty == Type::FP128Ty) { assert(0 && "Long double constants not handled yet."); @@ -305,6 +314,18 @@ ConstantFP *ConstantFP::get(const Type *Ty, double V) { } } +ConstantFP *ConstantFP::get(const Type *Ty, const APFloat& V) { + // temporary + if (Ty==Type::FloatTy) + assert(&V.getSemantics()==&APFloat::IEEEsingle); + else + assert(&V.getSemantics()==&APFloat::IEEEdouble); + + DenseMapAPFloatKeyInfo::KeyTy Key(V); + ConstantFP *&Slot = (*FPConstants)[Key]; + if (Slot) return Slot; + return Slot = new ConstantFP(Ty, V); +} //===----------------------------------------------------------------------===// // ConstantXXX Classes @@ -699,14 +720,24 @@ bool ConstantInt::isValueValidForType(const Type *Ty, int64_t Val) { return (Val >= Min && Val <= Max); } -bool ConstantFP::isValueValidForType(const Type *Ty, double Val) { +bool ConstantFP::isValueValidForType(const Type *Ty, const APFloat& Val) { + // convert modifies in place, so make a copy. + APFloat Val2 = APFloat(Val); switch (Ty->getTypeID()) { default: return false; // These can't be represented as floating point! - // TODO: Figure out how to test if we can use a shorter type instead! + // FIXME rounding mode needs to be more flexible case Type::FloatTyID: + return &Val2.getSemantics() == &APFloat::IEEEsingle || + Val2.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven) == + APFloat::opOK; case Type::DoubleTyID: + return &Val2.getSemantics() == &APFloat::IEEEsingle || + &Val2.getSemantics() == &APFloat::IEEEdouble || + Val2.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven) == + APFloat::opOK; + // TODO: Figure out how to test if we can use a shorter type instead! case Type::X86_FP80TyID: case Type::PPC_FP128TyID: case Type::FP128TyID: