aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDale Johannesen <dalej@apple.com>2007-09-14 22:26:36 +0000
committerDale Johannesen <dalej@apple.com>2007-09-14 22:26:36 +0000
commit9e3d3abd937c9bb79d56d25ec0e0724c7cbba67c (patch)
treec30fb34d6aa099b2c600d4a43088b7e99ef4e79b /lib
parent24f2ea3971065eb9e88d50ebeddad0463337cae3 (diff)
downloadexternal_llvm-9e3d3abd937c9bb79d56d25ec0e0724c7cbba67c.zip
external_llvm-9e3d3abd937c9bb79d56d25ec0e0724c7cbba67c.tar.gz
external_llvm-9e3d3abd937c9bb79d56d25ec0e0724c7cbba67c.tar.bz2
Remove the assumption that FP's are either float or
double from some of the many places in the optimizers it appears, and do something reasonable with x86 long double. Make APInt::dump() public, remove newline, use it to dump ConstantSDNode's. Allow APFloats in FoldingSet. Expand X86 backend handling of long doubles (conversions to/from int, mostly). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41967 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp41
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp28
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp5
-rw-r--r--lib/Support/APInt.cpp2
-rw-r--r--lib/Support/FoldingSet.cpp6
-rw-r--r--lib/Target/CBackend/CBackend.cpp3
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp32
-rw-r--r--lib/Target/X86/X86RegisterInfo.cpp8
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp9
-rw-r--r--lib/VMCore/Constants.cpp25
10 files changed, 108 insertions, 51 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index da55eaf..d709169 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/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<ConstantFP>(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<ConstantFPSDNode>(ST->getValue())) {
+ // We generally can't do this one for long doubles.
+ if (ConstantFPSDNode *CFP =dyn_cast<ConstantFPSDNode>(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/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 0defc12..3744c4a 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/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<ConstantFPSDNode>(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<ConstantFPSDNode>(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<ConstantSDNode>(this)) {
cerr << "<" << CSDN->getValue() << ">";
} else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(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 << "<APFloat(";
+ CSDN->getValueAPF().convertToAPInt().dump();
+ cerr << ")>";
+ }
} else if (const GlobalAddressSDNode *GADN =
dyn_cast<GlobalAddressSDNode>(this)) {
int offset = GADN->getOffset();
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 561b303..14691ee 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/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<Constant*> NZ(VL, ConstantFP::get(ElTy,
- ElTy==Type::FloatTy ? APFloat(-0.0f) : APFloat(-0.0)));
+ std::vector<Constant*> 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<ConstantFP>(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/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index 277a0b0..15de08e 100644
--- a/lib/Support/APInt.cpp
+++ b/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/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp
index 0ccb3a6..70daad9 100644
--- a/lib/Support/FoldingSet.cpp
+++ b/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; i<api.getNumWords(); i++)
+ AddInteger(*p++);
+}
void FoldingSetImpl::NodeID::AddString(const std::string &String) {
unsigned Size = String.size();
Bits.push_back(Size);
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index 9fc30c4..5f6d590 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -604,6 +604,9 @@ void CWriter::printConstantVector(ConstantVector *CP) {
// only deal in IEEE FP).
//
static bool isFPCSafeToPrint(const ConstantFP *CFP) {
+ // Do long doubles the hard way for now.
+ if (CFP->getType()!=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/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index b073887..55f37a6 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/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/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp
index 557f07e..4a8c275 100644
--- a/lib/Target/X86/X86RegisterInfo.cpp
+++ b/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/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 0343635..ab6262b 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/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<ConstantFP>(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<BinaryOperator>(Op0))
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index c546045..2bcd7b6 100644
--- a/lib/VMCore/Constants.cpp
+++ b/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<PointerType>(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 <ConstantFP>(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<VectorType>(Ty))
if (PTy->getElementType()->isFloatingPoint()) {
std::vector<Constant*> 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);
}