diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index 9a5643bfc5e1..c6055dfc27c5 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -153,11 +153,6 @@ class APInt { const APInt &RHS, uint32_t rhsWords, APInt *Quotient, APInt *Remainder); -#ifndef NDEBUG - /// @brief debug method - void dump() const; -#endif - public: /// @name Constructors /// @{ @@ -1165,6 +1160,11 @@ public: static void tcSetLeastSignificantBits(integerPart *, unsigned int, unsigned int bits); +#ifndef NDEBUG + /// @brief debug method + void dump() const; +#endif + /// @} }; diff --git a/llvm/include/llvm/ADT/FoldingSet.h b/llvm/include/llvm/ADT/FoldingSet.h index 155243a6277c..7fca63867ba6 100644 --- a/llvm/include/llvm/ADT/FoldingSet.h +++ b/llvm/include/llvm/ADT/FoldingSet.h @@ -18,6 +18,7 @@ #include "llvm/Support/DataTypes.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/APFloat.h" #include namespace llvm { @@ -153,6 +154,7 @@ public: void AddInteger(uint64_t I); void AddFloat(float F); void AddDouble(double D); + void AddAPFloat(const APFloat& apf); void AddString(const std::string &String); /// ComputeHash - Compute a strong hash value for this NodeID, used to diff --git a/llvm/include/llvm/Constants.h b/llvm/include/llvm/Constants.h index b6b3f6346f64..2f3ad9d6ebc0 100644 --- a/llvm/include/llvm/Constants.h +++ b/llvm/include/llvm/Constants.h @@ -231,6 +231,9 @@ public: /// considers -0.0 to be null as well as 0.0. :( virtual bool isNullValue() const; + // Get a negative zero. + static ConstantFP *getNegativeZero(const Type* Ty); + /// isExactlyValue - We don't rely on operator== working on double values, as /// 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 diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index da55eafdb28a..d709169d351f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -486,15 +486,23 @@ static SDOperand ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, // double. MVT::ValueType VT = CFP->getValueType(0); bool isDouble = VT == MVT::f64; - ConstantFP *LLVMC = ConstantFP::get(isDouble ? Type::DoubleTy : - Type::FloatTy, CFP->getValueAPF()); + ConstantFP *LLVMC = ConstantFP::get(VT==MVT::f64 ? Type::DoubleTy : + VT==MVT::f32 ? Type::FloatTy : + VT==MVT::f80 ? Type::X86_FP80Ty : + VT==MVT::f128 ? Type::FP128Ty : + VT==MVT::ppcf128 ? Type::PPC_FP128Ty : + Type::VoidTy, // error + CFP->getValueAPF()); if (!UseCP) { + if (VT!=MVT::f64 && VT!=MVT::f32) + assert(0 && "Invalid type expansion"); return DAG.getConstant(LLVMC->getValueAPF().convertToAPInt().getZExtValue(), isDouble ? MVT::i64 : MVT::i32); } if (isDouble && CFP->isValueValidForType(MVT::f32, CFP->getValueAPF()) && // Only do this if the target has a native EXTLOAD instruction from f32. + // Do not try to be clever about long doubles (so far) TLI.isLoadXLegal(ISD::EXTLOAD, MVT::f32)) { LLVMC = cast(ConstantExpr::getFPTrunc(LLVMC,Type::FloatTy)); VT = MVT::f32; @@ -1976,19 +1984,22 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { // to phase ordering between legalized code and the dag combiner. This // probably means that we need to integrate dag combiner and legalizer // together. - if (ConstantFPSDNode *CFP = dyn_cast(ST->getValue())) { + // We generally can't do this one for long doubles. + if (ConstantFPSDNode *CFP =dyn_cast(ST->getValue())) { if (CFP->getValueType(0) == MVT::f32) { Tmp3 = DAG.getConstant((uint32_t)CFP->getValueAPF(). convertToAPInt().getZExtValue(), MVT::i32); - } else { - assert(CFP->getValueType(0) == MVT::f64 && "Unknown FP type!"); + Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(), + SVOffset, isVolatile, Alignment); + break; + } else if (CFP->getValueType(0) == MVT::f64) { Tmp3 = DAG.getConstant(CFP->getValueAPF().convertToAPInt(). getZExtValue(), MVT::i64); + Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(), + SVOffset, isVolatile, Alignment); + break; } - Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(), - SVOffset, isVolatile, Alignment); - break; } switch (getTypeAction(ST->getStoredVT())) { @@ -4609,12 +4620,16 @@ ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) { SDOperand FudgeInReg; if (DestTy == MVT::f32) FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0); - else { - assert(DestTy == MVT::f64 && "Unexpected conversion"); + else if (DestTy == MVT::f64) // FIXME: Avoid the extend by construction the right constantpool? FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(), CPIdx, NULL, 0, MVT::f32); - } + else if (DestTy == MVT::f80) + FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, MVT::f80, DAG.getEntryNode(), + CPIdx, NULL, 0, MVT::f32); + else + assert(0 && "Unexpected conversion"); + MVT::ValueType SCVT = SignedConv.getValueType(); if (SCVT != DestTy) { // Destination type needs to be expanded as well. The FADD now we are @@ -4722,9 +4737,11 @@ SDOperand SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, if (DestVT == MVT::f64) { // do nothing Result = Sub; - } else { + } else if (DestVT == MVT::f32) { // if f32 then cast to f32 Result = DAG.getNode(ISD::FP_ROUND, MVT::f32, Sub); + } else if (DestVT == MVT::f80) { + Result = DAG.getNode(ISD::FP_EXTEND, MVT::f80, Sub); } return Result; } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 0defc12e05e8..3744c4ad663a 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -322,13 +322,7 @@ static void AddNodeIDNode(FoldingSetNodeID &ID, SDNode *N) { break; case ISD::TargetConstantFP: case ISD::ConstantFP: { - APFloat V = cast(N)->getValueAPF(); - if (&V.getSemantics() == &APFloat::IEEEdouble) - ID.AddDouble(V.convertToDouble()); - else if (&V.getSemantics() == &APFloat::IEEEsingle) - ID.AddDouble((double)V.convertToFloat()); - else - assert(0); + ID.AddAPFloat(cast(N)->getValueAPF()); break; } case ISD::TargetGlobalAddress: @@ -709,25 +703,21 @@ SDOperand SelectionDAG::getConstantFP(const APFloat& V, MVT::ValueType VT, MVT::ValueType EltVT = MVT::isVector(VT) ? MVT::getVectorElementType(VT) : VT; - 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); + ID.AddAPFloat(V); void *IP = 0; SDNode *N = NULL; if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) if (!MVT::isVector(VT)) return SDOperand(N, 0); if (!N) { - N = new ConstantFPSDNode(isTarget, - isDouble ? APFloat(Val) : APFloat((float)Val), EltVT); + N = new ConstantFPSDNode(isTarget, V, EltVT); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); } @@ -3724,9 +3714,15 @@ void SDNode::dump(const SelectionDAG *G) const { if (const ConstantSDNode *CSDN = dyn_cast(this)) { cerr << "<" << CSDN->getValue() << ">"; } else if (const ConstantFPSDNode *CSDN = dyn_cast(this)) { - cerr << "<" << (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEsingle ? - CSDN->getValueAPF().convertToFloat() : - CSDN->getValueAPF().convertToDouble()) << ">"; + if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEsingle) + cerr << "<" << CSDN->getValueAPF().convertToFloat() << ">"; + else if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEdouble) + cerr << "<" << CSDN->getValueAPF().convertToDouble() << ">"; + else { + cerr << "getValueAPF().convertToAPInt().dump(); + cerr << ")>"; + } } else if (const GlobalAddressSDNode *GADN = dyn_cast(this)) { int offset = GADN->getOffset(); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 561b303f7086..14691ee485bb 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2004,8 +2004,7 @@ void SelectionDAGLowering::visitSub(User &I) { const Type *ElTy = DestTy->getElementType(); if (ElTy->isFloatingPoint()) { unsigned VL = DestTy->getNumElements(); - std::vector NZ(VL, ConstantFP::get(ElTy, - ElTy==Type::FloatTy ? APFloat(-0.0f) : APFloat(-0.0))); + std::vector NZ(VL, ConstantFP::getNegativeZero(ElTy)); Constant *CNZ = ConstantVector::get(&NZ[0], NZ.size()); if (CV == CNZ) { SDOperand Op2 = getValue(I.getOperand(1)); @@ -2017,7 +2016,7 @@ void SelectionDAGLowering::visitSub(User &I) { } if (Ty->isFloatingPoint()) { if (ConstantFP *CFP = dyn_cast(I.getOperand(0))) - if (CFP->isExactlyValue(-0.0)) { + if (CFP->isExactlyValue(ConstantFP::getNegativeZero(Ty)->getValueAPF())) { SDOperand Op2 = getValue(I.getOperand(1)); setValue(&I, DAG.getNode(ISD::FNEG, Op2.getValueType(), Op2)); return; diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 277a0b0c113c..15de08ed055a 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -2009,7 +2009,7 @@ void APInt::dump() const cerr << pVal[i-1] << " "; } cerr << " U(" << this->toStringUnsigned(10) << ") S(" - << this->toStringSigned(10) << ")\n" << std::setbase(10); + << this->toStringSigned(10) << ")" << std::setbase(10); } #endif diff --git a/llvm/lib/Support/FoldingSet.cpp b/llvm/lib/Support/FoldingSet.cpp index 0ccb3a6cc328..70daad9a6195 100644 --- a/llvm/lib/Support/FoldingSet.cpp +++ b/llvm/lib/Support/FoldingSet.cpp @@ -56,6 +56,12 @@ void FoldingSetImpl::NodeID::AddFloat(float F) { void FoldingSetImpl::NodeID::AddDouble(double D) { AddInteger(DoubleToBits(D)); } +void FoldingSetImpl::NodeID::AddAPFloat(const APFloat& apf) { + APInt api = apf.convertToAPInt(); + const uint64_t *p = api.getRawData(); + for (int i=0; igetType()!=Type::FloatTy && CFP->getType()!=Type::DoubleTy) + return false; APFloat APF = APFloat(CFP->getValueAPF()); // copy if (CFP->getType()==Type::FloatTy) APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven); diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index b073887bd104..55f37a658465 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -99,9 +99,11 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) setOperationAction(ISD::SINT_TO_FP , MVT::i1 , Promote); setOperationAction(ISD::SINT_TO_FP , MVT::i8 , Promote); // SSE has no i16 to fp conversion, only i32 - if (X86ScalarSSE) + if (X86ScalarSSE) { setOperationAction(ISD::SINT_TO_FP , MVT::i16 , Promote); - else { + // f32 and f64 cases are Legal, f80 case is not + setOperationAction(ISD::SINT_TO_FP , MVT::i32 , Custom); + } else { setOperationAction(ISD::SINT_TO_FP , MVT::i16 , Custom); setOperationAction(ISD::SINT_TO_FP , MVT::i32 , Custom); } @@ -119,6 +121,8 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) if (X86ScalarSSE) { setOperationAction(ISD::FP_TO_SINT , MVT::i16 , Promote); + // f32 and f64 cases are Legal, f80 case is not + setOperationAction(ISD::FP_TO_SINT , MVT::i32 , Custom); } else { setOperationAction(ISD::FP_TO_SINT , MVT::i16 , Custom); setOperationAction(ISD::FP_TO_SINT , MVT::i32 , Custom); @@ -189,11 +193,13 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) setOperationAction(ISD::SELECT , MVT::i32 , Custom); setOperationAction(ISD::SELECT , MVT::f32 , Custom); setOperationAction(ISD::SELECT , MVT::f64 , Custom); + setOperationAction(ISD::SELECT , MVT::f80 , Custom); setOperationAction(ISD::SETCC , MVT::i8 , Custom); setOperationAction(ISD::SETCC , MVT::i16 , Custom); setOperationAction(ISD::SETCC , MVT::i32 , Custom); setOperationAction(ISD::SETCC , MVT::f32 , Custom); setOperationAction(ISD::SETCC , MVT::f64 , Custom); + setOperationAction(ISD::SETCC , MVT::f80 , Custom); if (Subtarget->is64Bit()) { setOperationAction(ISD::SELECT , MVT::i64 , Custom); setOperationAction(ISD::SETCC , MVT::i64 , Custom); @@ -334,6 +340,9 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) // Long double always uses X87. addRegisterClass(MVT::f80, X86::RFP80RegisterClass); + setOperationAction(ISD::UNDEF, MVT::f80, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f80, Expand); + setOperationAction(ISD::ConstantFP, MVT::f80, Expand); // First set operation action for all vector types to expand. Then we // will selectively turn on ones that can be effectively codegen'd. @@ -3326,9 +3335,14 @@ SDOperand X86TargetLowering::LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) { SDOperand Chain = DAG.getStore(DAG.getEntryNode(), Op.getOperand(0), StackSlot, NULL, 0); + // These are really Legal; caller falls through into that case. + if (SrcVT==MVT::i32 && Op.getValueType() != MVT::f80 && X86ScalarSSE) + return Result; + // Build the FILD SDVTList Tys; - if (X86ScalarSSE) + bool useSSE = X86ScalarSSE && Op.getValueType() != MVT::f80; + if (useSSE) Tys = DAG.getVTList(MVT::f64, MVT::Other, MVT::Flag); else Tys = DAG.getVTList(Op.getValueType(), MVT::Other); @@ -3336,10 +3350,10 @@ SDOperand X86TargetLowering::LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) { Ops.push_back(Chain); Ops.push_back(StackSlot); Ops.push_back(DAG.getValueType(SrcVT)); - Result = DAG.getNode(X86ScalarSSE ? X86ISD::FILD_FLAG :X86ISD::FILD, + Result = DAG.getNode(useSSE ? X86ISD::FILD_FLAG :X86ISD::FILD, Tys, &Ops[0], Ops.size()); - if (X86ScalarSSE) { + if (useSSE) { Chain = Result.getValue(1); SDOperand InFlag = Result.getValue(2); @@ -3368,11 +3382,17 @@ SDOperand X86TargetLowering::LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) { "Unknown FP_TO_SINT to lower!"); // We lower FP->sint64 into FISTP64, followed by a load, all to a temporary // stack slot. + SDOperand Result; MachineFunction &MF = DAG.getMachineFunction(); unsigned MemSize = MVT::getSizeInBits(Op.getValueType())/8; int SSFI = MF.getFrameInfo()->CreateStackObject(MemSize, MemSize); SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy()); + // These are really Legal. + if (Op.getValueType() == MVT::i32 && X86ScalarSSE && + Op.getOperand(0).getValueType() != MVT::f80) + return Result; + unsigned Opc; switch (Op.getValueType()) { default: assert(0 && "Invalid FP_TO_SINT to lower!"); @@ -3383,7 +3403,7 @@ SDOperand X86TargetLowering::LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) { SDOperand Chain = DAG.getEntryNode(); SDOperand Value = Op.getOperand(0); - if (X86ScalarSSE) { + if (X86ScalarSSE && Op.getOperand(0).getValueType() != MVT::f80) { assert(Op.getValueType() == MVT::i64 && "Invalid FP_TO_SINT to lower!"); Chain = DAG.getStore(Chain, Value, StackSlot, NULL, 0); SDVTList Tys = DAG.getVTList(Op.getOperand(0).getValueType(), MVT::Other); diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp index 557f07e8b404..4a8c275bc54e 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -168,7 +168,11 @@ void X86RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB, Opc = X86::MOV32_mr; } else if (RC == &X86::GR16_RegClass) { Opc = X86::MOV16_mr; + } else if (RC == &X86::RFP80RegClass) { + Opc = X86::ST_FpP80m; // pops } else if (RC == &X86::RFP64RegClass || RC == &X86::RSTRegClass) { + /// FIXME spilling long double values as 64 bit does not work. + /// We need RST80, unfortunately. Opc = X86::ST_Fp64m; } else if (RC == &X86::RFP32RegClass) { Opc = X86::ST_Fp32m; @@ -205,6 +209,8 @@ void X86RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, Opc = X86::MOV32_rm; } else if (RC == &X86::GR16_RegClass) { Opc = X86::MOV16_rm; + } else if (RC == &X86::RFP80RegClass) { + Opc = X86::LD_Fp80m; } else if (RC == &X86::RFP64RegClass || RC == &X86::RSTRegClass) { Opc = X86::LD_Fp64m; } else if (RC == &X86::RFP32RegClass) { @@ -245,6 +251,8 @@ void X86RegisterInfo::copyRegToReg(MachineBasicBlock &MBB, Opc = X86::MOV_Fp3232; } else if (RC == &X86::RFP64RegClass || RC == &X86::RSTRegClass) { Opc = X86::MOV_Fp6464; + } else if (RC == &X86::RFP80RegClass) { + Opc = X86::MOV_Fp8080; } else if (RC == &X86::FR32RegClass) { Opc = X86::FsMOVAPSrr; } else if (RC == &X86::FR64RegClass) { diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp index 034363527000..ab6262b47e53 100644 --- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp @@ -1949,7 +1949,8 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { if (RHSC->isNullValue()) return ReplaceInstUsesWith(I, LHS); } else if (ConstantFP *CFP = dyn_cast(RHSC)) { - if (CFP->isExactlyValue(-0.0)) + if (CFP->isExactlyValue(ConstantFP::getNegativeZero + (I.getType())->getValueAPF())) return ReplaceInstUsesWith(I, LHS); } @@ -2349,8 +2350,10 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { // "In IEEE floating point, x*1 is not equivalent to x for nans. However, // ANSI says we can drop signals, so we can do this anyway." (from GCC) - if (Op1F->isExactlyValue(1.0)) - return ReplaceInstUsesWith(I, Op0); // Eliminate 'mul double %X, 1.0' + // We need a better interface for long double here. + if (Op1->getType() == Type::FloatTy || Op1->getType() == Type::DoubleTy) + if (Op1F->isExactlyValue(1.0)) + return ReplaceInstUsesWith(I, Op0); // Eliminate 'mul double %X, 1.0' } if (BinaryOperator *Op0I = dyn_cast(Op0)) diff --git a/llvm/lib/VMCore/Constants.cpp b/llvm/lib/VMCore/Constants.cpp index c54604545421..2bcd7b68b75f 100644 --- a/llvm/lib/VMCore/Constants.cpp +++ b/llvm/lib/VMCore/Constants.cpp @@ -103,17 +103,19 @@ bool Constant::ContainsRelocations() const { // Static constructor to create a '0' constant of arbitrary type... Constant *Constant::getNullValue(const Type *Ty) { + static uint64_t zero[2] = {0, 0}; switch (Ty->getTypeID()) { case Type::IntegerTyID: return ConstantInt::get(Ty, 0); case Type::FloatTyID: - return ConstantFP::get(Ty, APFloat(0.0f)); + return ConstantFP::get(Ty, APFloat(APInt(32, 0))); case Type::DoubleTyID: - return ConstantFP::get(Ty, APFloat(0.0)); + return ConstantFP::get(Ty, APFloat(APInt(64, 0))); case Type::X86_FP80TyID: - case Type::PPC_FP128TyID: + return ConstantFP::get(Ty, APFloat(APInt(80, 2, zero))); case Type::FP128TyID: - return ConstantFP::get(Ty, APFloat(0.0)); //FIXME + case Type::PPC_FP128TyID: + return ConstantFP::get(Ty, APFloat(APInt(128, 2, zero))); case Type::PointerTyID: return ConstantPointerNull::get(cast(Ty)); case Type::StructTyID: @@ -259,6 +261,12 @@ bool ConstantFP::isNullValue() const { return Val.isZero() && !Val.isNegative(); } +ConstantFP *ConstantFP::getNegativeZero(const Type *Ty) { + APFloat apf = cast (Constant::getNullValue(Ty))->getValueAPF(); + apf.changeSign(); + return ConstantFP::get(Ty, apf); +} + bool ConstantFP::isExactlyValue(const APFloat& V) const { return Val.bitwiseIsEqual(V); } @@ -1925,15 +1933,12 @@ Constant *ConstantExpr::getZeroValueForNegationExpr(const Type *Ty) { if (const VectorType *PTy = dyn_cast(Ty)) if (PTy->getElementType()->isFloatingPoint()) { std::vector zeros(PTy->getNumElements(), - ConstantFP::get(PTy->getElementType(), - PTy->getElementType()==Type::FloatTy ? - APFloat(-0.0f) : APFloat(0.0))); + ConstantFP::getNegativeZero(PTy->getElementType())); return ConstantVector::get(PTy, zeros); } - if (Ty->isFloatingPoint()) - return ConstantFP::get(Ty, Ty==Type::FloatTy ? APFloat(-0.0f) : - APFloat(-0.0)); + if (Ty->isFloatingPoint()) + return ConstantFP::getNegativeZero(Ty); return Constant::getNullValue(Ty); }