Very sorry for that massive redundant attachment if it got through. Clicked
the wrong file.
Ping? Particularly for the Clang folks, one of whom I was rather hoping would
give me a good slapping and tell me how I should be serialising APFloats.
Tim.
On Tuesday 08 Jan 2013 14:14:47 Tim Northover wrote:
> On Monday 07 Jan 2013 16:22:14 Renato Golin wrote:
> > I thought as much... I don't know about others, but I feel that PPC
> > should be the special case here, not IEEE. Though, it has nothing to do
> > with your patch.
>
> I've got some updated patches here that remove any default behaviour; as
> Duncan pointed out it *is* largely inappropriate. The new interface is
>
> APFloat::APFloat(const fltSemantics&, const APInt&)
>
> On the whole it turned out rather neatly. When needed, the fltSemantics
> were usually easy to come by, even though there's a redundancy in APInt
> size and semantics for the smaller cases.
>
> I experimented with alternatives before settling on this (ignore names):
>
> APFloat::APFloat(const APInt&) // Faults if 128-bit attempted
> APFloat::getIEEEQuad(const APInt&)
> APFloat::getPPCDblDbl(const APInt&)
>
> This seemed promising, but there were lots of places where code wanted to
> all floating-point types, so some generic function was beneficial, and at
> that point is it really worth adding a helper that only works for types <
> 64 bits. You can bet someone will use it without thinking things through
> properly.
>
> APFloat::APFloat(const APInt&, enum { irrelevent, ieee128, ppc128 })
>
> This was basically the same as the chosen variant, except that it
> introduced a largely redundant enum.
>
> I'm much less certain about the patch to Clang. What was there was clearly
> wrong: AST serialisation didn't save the IsIEEE property, however there's
> no existing good way to serialise an fltSemantics. Is there a better way
> I've missed, or should I put the enum in a more standard place? There
> didn't seem to be a directly equivalent construct.
>
> Tim.
>
> -- IMPORTANT NOTICE: The contents of this email and any attachments are
> confidential and may also be privileged. If you are not the intended
> recipient, please notify the sender immediately and do not disclose the
> contents to any other person, use it for any purpose, or store or copy the
> information in any medium. Thank you.diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index cbb800e..5fbe791 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -1212,11 +1212,13 @@ public:
};
class APFloatStorage : private APNumericStorage {
+ const llvm::fltSemantics *Semantics;
public:
- llvm::APFloat getValue(bool IsIEEE) const {
- return llvm::APFloat(getIntValue(), IsIEEE);
+ llvm::APFloat getValue() const {
+ return llvm::APFloat(*Semantics, getIntValue());
}
void setValue(ASTContext &C, const llvm::APFloat &Val) {
+ Semantics = &Val.getSemantics();
setIntValue(C, Val.bitcastToAPInt());
}
};
@@ -1321,7 +1323,7 @@ public:
static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty);
llvm::APFloat getValue() const {
- return APFloatStorage::getValue(FloatingLiteralBits.IsIEEE);
+ return APFloatStorage::getValue();
}
void setValue(ASTContext &C, const llvm::APFloat &Val) {
APFloatStorage::setValue(C, Val);
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index e475c38..1a3492a 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -178,7 +178,6 @@ protected:
friend class FloatingLiteral;
unsigned : NumExprBits;
- unsigned IsIEEE : 1; // Distinguishes between PPC128 and IEEE128.
unsigned IsExact : 1;
};
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 5689d9c..c3412e0 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -646,16 +646,12 @@ FloatingLiteral::FloatingLiteral(ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L)
: Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
false, false), Loc(L) {
- FloatingLiteralBits.IsIEEE =
- &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad;
FloatingLiteralBits.IsExact = isexact;
setValue(C, V);
}
FloatingLiteral::FloatingLiteral(ASTContext &C, EmptyShell Empty)
: Expr(FloatingLiteralClass, Empty) {
- FloatingLiteralBits.IsIEEE =
- &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad;
FloatingLiteralBits.IsExact = false;
}
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 338cd74..ddc06d6 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -3630,7 +3630,6 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
SmallVector<APValue, 4> Elts;
if (EltTy->isRealFloatingType()) {
const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy);
- bool isIEESem = &Sem != &APFloat::PPCDoubleDouble;
unsigned FloatEltSize = EltSize;
if (&Sem == &APFloat::x87DoubleExtended)
FloatEltSize = 80;
@@ -3640,7 +3639,7 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
Elt = SValInt.rotl(i*EltSize+FloatEltSize).trunc(FloatEltSize);
else
Elt = SValInt.rotr(i*EltSize).trunc(FloatEltSize);
- Elts.push_back(APValue(APFloat(Elt, isIEESem)));
+ Elts.push_back(APValue(APFloat(Sem, Elt)));
}
} else if (EltTy->isIntegerType()) {
for (unsigned i = 0; i < NElts; i++) {
diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h
index 643deb2..5ec6257 100644
--- a/lib/Serialization/ASTCommon.h
+++ b/lib/Serialization/ASTCommon.h
@@ -28,6 +28,15 @@ enum DeclUpdateKind {
UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER
};
+enum APFloatSemantics {
+ IEEEhalf,
+ IEEEsingle,
+ IEEEdouble,
+ x87DoubleExtended,
+ IEEEquad,
+ PPCDoubleDouble
+};
+
TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);
template <typename IdxForTypeTy>
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index eca9918..28c70bc 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -6717,7 +6717,30 @@ llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
/// \brief Read a floating-point value
llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
- return llvm::APFloat(ReadAPInt(Record, Idx));
+ APFloatSemantics Semantics = static_cast<APFloatSemantics>(Record[Idx++]);
+ const llvm::fltSemantics *Sem;
+ switch (Semantics) {
+ case IEEEhalf:
+ Sem = &llvm::APFloat::IEEEhalf;
+ break;
+ case IEEEsingle:
+ Sem = &llvm::APFloat::IEEEsingle;
+ break;
+ case IEEEdouble:
+ Sem = &llvm::APFloat::IEEEdouble;
+ break;
+ case x87DoubleExtended:
+ Sem = &llvm::APFloat::x87DoubleExtended;
+ break;
+ case IEEEquad:
+ Sem = &llvm::APFloat::IEEEquad;
+ break;
+ case PPCDoubleDouble:
+ Sem = &llvm::APFloat::PPCDoubleDouble;
+ break;
+ }
+
+ return llvm::APFloat(*Sem, ReadAPInt(Record, Idx));
}
// \brief Read a string
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index ac24098..b2c6049 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -3935,6 +3935,24 @@ void ASTWriter::AddAPSInt(const llvm::APSInt &Value, RecordDataImpl &Record) {
}
void ASTWriter::AddAPFloat(const llvm::APFloat &Value, RecordDataImpl &Record) {
+ APFloatSemantics Semantics;
+ const llvm::fltSemantics *Sem = &Value.getSemantics();
+ if (Sem == &llvm::APFloat::IEEEhalf)
+ Semantics = IEEEhalf;
+ else if (Sem == &llvm::APFloat::IEEEsingle)
+ Semantics = IEEEsingle;
+ else if (Sem == &llvm::APFloat::IEEEdouble)
+ Semantics = IEEEdouble;
+ else if (Sem == &llvm::APFloat::x87DoubleExtended)
+ Semantics = x87DoubleExtended;
+ else if (Sem == &llvm::APFloat::IEEEquad)
+ Semantics = IEEEquad;
+ else if (Sem == &llvm::APFloat::PPCDoubleDouble)
+ Semantics = PPCDoubleDouble;
+ else
+ llvm_unreachable("Unknown floating semantics");
+
+ Record.push_back(Semantics);
AddAPInt(Value.bitcastToAPInt(), Record);
}
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h
index 93d343a..3553307 100644
--- a/include/llvm/ADT/APFloat.h
+++ b/include/llvm/ADT/APFloat.h
@@ -184,9 +184,9 @@ namespace llvm {
APFloat(const fltSemantics &, integerPart);
APFloat(const fltSemantics &, fltCategory, bool negative);
APFloat(const fltSemantics &, uninitializedTag);
+ APFloat(const fltSemantics &, const APInt &);
explicit APFloat(double d);
explicit APFloat(float f);
- explicit APFloat(const APInt &, bool isIEEE = false);
APFloat(const APFloat &);
~APFloat();
@@ -423,7 +423,7 @@ namespace llvm {
APInt convertQuadrupleAPFloatToAPInt() const;
APInt convertF80LongDoubleAPFloatToAPInt() const;
APInt convertPPCDoubleDoubleAPFloatToAPInt() const;
- void initFromAPInt(const APInt& api, bool isIEEE = false);
+ void initFromAPInt(const fltSemantics *Sem, const APInt& api);
void initFromHalfAPInt(const APInt& api);
void initFromFloatAPInt(const APInt& api);
void initFromDoubleAPInt(const APInt& api);
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index c5cc8f5..9a6035a 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -935,6 +935,20 @@ public:
}
}
+ /// Returns an APFloat semantics tag appropriate for the given type. If VT is
+ /// a vector type, the element semantics are returned
+ static const fltSemantics &EVTToAPFloatSemantics(EVT VT) {
+ switch (VT.getScalarType().getSimpleVT().SimpleTy) {
+ default: llvm_unreachable("Unknown FP format");
+ case MVT::f16: return APFloat::IEEEhalf;
+ case MVT::f32: return APFloat::IEEEsingle;
+ case MVT::f64: return APFloat::IEEEdouble;
+ case MVT::f80: return APFloat::x87DoubleExtended;
+ case MVT::f128: return APFloat::IEEEquad;
+ case MVT::ppcf128: return APFloat::PPCDoubleDouble;
+ }
+ }
+
/// AssignOrdering - Assign an order to the SDNode.
void AssignOrdering(const SDNode *SD, unsigned Order);
diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h
index def4575..2846e47 100644
--- a/include/llvm/IR/Type.h
+++ b/include/llvm/IR/Type.h
@@ -15,6 +15,7 @@
#ifndef LLVM_TYPE_H
#define LLVM_TYPE_H
+#include "llvm/ADT/APFloat.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
@@ -162,6 +163,18 @@ public:
getTypeID() == PPC_FP128TyID;
}
+ const fltSemantics &getFltSemantics() const {
+ switch (getTypeID()) {
+ case HalfTyID: return APFloat::IEEEhalf;
+ case FloatTyID: return APFloat::IEEEsingle;
+ case DoubleTyID: return APFloat::IEEEdouble;
+ case X86_FP80TyID: return APFloat::x87DoubleExtended;
+ case FP128TyID: return APFloat::IEEEquad;
+ case PPC_FP128TyID: return APFloat::PPCDoubleDouble;
+ default: return APFloat::Bogus;
+ }
+ }
+
/// isX86_MMXTy - Return true if this is X86 MMX.
bool isX86_MMXTy() const { return getTypeID() == X86_MMXTyID; }
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index 2b7d3bd..e2b1e25 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/lib/Analysis/ConstantFolding.cpp
@@ -1337,7 +1337,7 @@ llvm::ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands,
case Intrinsic::ctpop:
return ConstantInt::get(Ty, Op->getValue().countPopulation());
case Intrinsic::convert_from_fp16: {
- APFloat Val(Op->getValue());
+ APFloat Val(APFloat::IEEEhalf, Op->getValue());
bool lost = false;
APFloat::opStatus status =
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index 32e709c..b8cd165 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -722,20 +722,21 @@ lltok::Kind LLLexer::Lex0x() {
case 'K':
// F80HexFPConstant - x87 long double in hexadecimal format (10 bytes)
FP80HexToIntPair(TokStart+3, CurPtr, Pair);
- APFloatVal = APFloat(APInt(80, Pair));
+ APFloatVal = APFloat(APFloat::x87DoubleExtended, APInt(80, Pair));
return lltok::APFloat;
case 'L':
// F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes)
HexToIntPair(TokStart+3, CurPtr, Pair);
- APFloatVal = APFloat(APInt(128, Pair), true);
+ APFloatVal = APFloat(APFloat::IEEEquad, APInt(128, Pair));
return lltok::APFloat;
case 'M':
// PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes)
HexToIntPair(TokStart+3, CurPtr, Pair);
- APFloatVal = APFloat(APInt(128, Pair));
+ APFloatVal = APFloat(APFloat::PPCDoubleDouble, APInt(128, Pair));
return lltok::APFloat;
case 'H':
- APFloatVal = APFloat(APInt(16,HexIntToVal(TokStart+3, CurPtr)));
+ APFloatVal = APFloat(APFloat::IEEEhalf,
+ APInt(16,HexIntToVal(TokStart+3, CurPtr)));
return lltok::APFloat;
}
}
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 59cda22..b499116 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1013,21 +1013,27 @@ bool BitcodeReader::ParseConstants() {
if (Record.empty())
return Error("Invalid FLOAT record");
if (CurTy->isHalfTy())
- V = ConstantFP::get(Context, APFloat(APInt(16, (uint16_t)Record[0])));
+ V = ConstantFP::get(Context, APFloat(APFloat::IEEEhalf,
+ APInt(16, (uint16_t)Record[0])));
else if (CurTy->isFloatTy())
- V = ConstantFP::get(Context, APFloat(APInt(32, (uint32_t)Record[0])));
+ V = ConstantFP::get(Context, APFloat(APFloat::IEEEsingle,
+ APInt(32, (uint32_t)Record[0])));
else if (CurTy->isDoubleTy())
- V = ConstantFP::get(Context, APFloat(APInt(64, Record[0])));
+ V = ConstantFP::get(Context, APFloat(APFloat::IEEEdouble,
+ APInt(64, Record[0])));
else if (CurTy->isX86_FP80Ty()) {
// Bits are not stored the same way as a normal i80 APInt, compensate.
uint64_t Rearrange[2];
Rearrange[0] = (Record[1] & 0xffffLL) | (Record[0] << 16);
Rearrange[1] = Record[0] >> 48;
- V = ConstantFP::get(Context, APFloat(APInt(80, Rearrange)));
+ V = ConstantFP::get(Context, APFloat(APFloat::x87DoubleExtended,
+ APInt(80, Rearrange)));
} else if (CurTy->isFP128Ty())
- V = ConstantFP::get(Context, APFloat(APInt(128, Record), true));
+ V = ConstantFP::get(Context, APFloat(APFloat::IEEEquad,
+ APInt(128, Record)));
else if (CurTy->isPPC_FP128Ty())
- V = ConstantFP::get(Context, APFloat(APInt(128, Record)));
+ V = ConstantFP::get(Context, APFloat(APFloat::PPCDoubleDouble,
+ APInt(128, Record)));
else
V = UndefValue::get(CurTy);
break;
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 037628d..b116a84 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -2823,7 +2823,8 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
SDValue True, False;
EVT VT = Node->getOperand(0).getValueType();
EVT NVT = Node->getValueType(0);
- APFloat apf(APInt::getNullValue(VT.getSizeInBits()));
+ APFloat apf(DAG.EVTToAPFloatSemantics(VT),
+ APInt::getNullValue(VT.getSizeInBits()));
APInt x = APInt::getSignBit(NVT.getSizeInBits());
(void)apf.convertFromAPInt(x, false, APFloat::rmNearestTiesToEven);
Tmp1 = DAG.getConstantFP(apf, VT);
diff --git a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 92dc5a9..f476820 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -886,9 +886,11 @@ void DAGTypeLegalizer::ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo,
assert(NVT.getSizeInBits() == integerPartWidth &&
"Do not know how to expand this float constant!");
APInt C = cast<ConstantFPSDNode>(N)->getValueAPF().bitcastToAPInt();
- Lo = DAG.getConstantFP(APFloat(APInt(integerPartWidth, C.getRawData()[1])),
+ Lo = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT),
+ APInt(integerPartWidth, C.getRawData()[1])),
NVT);
- Hi = DAG.getConstantFP(APFloat(APInt(integerPartWidth, C.getRawData()[0])),
+ Hi = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT),
+ APInt(integerPartWidth, C.getRawData()[0])),
NVT);
}
@@ -1060,7 +1062,8 @@ void DAGTypeLegalizer::ExpandFloatRes_FP_EXTEND(SDNode *N, SDValue &Lo,
SDValue &Hi) {
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
Hi = DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), NVT, N->getOperand(0));
- Lo = DAG.getConstantFP(APFloat(APInt(NVT.getSizeInBits(), 0)), NVT);
+ Lo = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT),
+ APInt(NVT.getSizeInBits(), 0)), NVT);
}
void DAGTypeLegalizer::ExpandFloatRes_FPOW(SDNode *N,
@@ -1155,7 +1158,8 @@ void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo,
Chain = Hi.getValue(1);
// The low part is zero.
- Lo = DAG.getConstantFP(APFloat(APInt(NVT.getSizeInBits(), 0)), NVT);
+ Lo = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT),
+ APInt(NVT.getSizeInBits(), 0)), NVT);
// Modified the chain - switch anything that used the old chain to use the
// new one.
@@ -1179,7 +1183,8 @@ void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo,
// The integer can be represented exactly in an f64.
Src = DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl,
MVT::i32, Src);
- Lo = DAG.getConstantFP(APFloat(APInt(NVT.getSizeInBits(), 0)), NVT);
+ Lo = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT),
+ APInt(NVT.getSizeInBits(), 0)), NVT);
Hi = DAG.getNode(ISD::SINT_TO_FP, dl, NVT, Src);
} else {
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
@@ -1225,7 +1230,8 @@ void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo,
}
Lo = DAG.getNode(ISD::FADD, dl, VT, Hi,
- DAG.getConstantFP(APFloat(APInt(128, Parts)),
+ DAG.getConstantFP(APFloat(APFloat::PPCDoubleDouble,
+ APInt(128, Parts)),
MVT::ppcf128));
Lo = DAG.getNode(ISD::SELECT_CC, dl, VT, Src, DAG.getConstant(0, SrcVT),
Lo, Hi, DAG.getCondCode(ISD::SETLT));
@@ -1377,7 +1383,7 @@ SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_UINT(SDNode *N) {
assert(N->getOperand(0).getValueType() == MVT::ppcf128 &&
"Logic only correct for ppcf128!");
const uint64_t TwoE31[] = {0x41e0000000000000LL, 0};
- APFloat APF = APFloat(APInt(128, TwoE31));
+ APFloat APF = APFloat(APFloat::PPCDoubleDouble, APInt(128, TwoE31));
SDValue Tmp = DAG.getConstantFP(APF, MVT::ppcf128);
// X>=2^31 ? (int)(X-2^31)+0x80000000 : (int)X
// FIXME: generated code sucks.
diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 5e33ef1..adcf4a0 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -2764,17 +2764,6 @@ SDValue DAGTypeLegalizer::ExpandIntOp_TRUNCATE(SDNode *N) {
return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), N->getValueType(0), InL);
}
-static const fltSemantics *EVTToAPFloatSemantics(EVT VT) {
- switch (VT.getSimpleVT().SimpleTy) {
- default: llvm_unreachable("Unknown FP format");
- case MVT::f32: return &APFloat::IEEEsingle;
- case MVT::f64: return &APFloat::IEEEdouble;
- case MVT::f80: return &APFloat::x87DoubleExtended;
- case MVT::f128: return &APFloat::IEEEquad;
- case MVT::ppcf128: return &APFloat::PPCDoubleDouble;
- }
-}
-
SDValue DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDNode *N) {
SDValue Op = N->getOperand(0);
EVT SrcVT = Op.getValueType();
@@ -2784,8 +2773,8 @@ SDValue DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDNode *N) {
// The following optimization is valid only if every value in SrcVT (when
// treated as signed) is representable in DstVT. Check that the mantissa
// size of DstVT is >= than the number of bits in SrcVT -1.
- const fltSemantics *sem = EVTToAPFloatSemantics(DstVT);
- if (APFloat::semanticsPrecision(*sem) >= SrcVT.getSizeInBits()-1 &&
+ const fltSemantics &sem = DAG.EVTToAPFloatSemantics(DstVT);
+ if (APFloat::semanticsPrecision(sem) >= SrcVT.getSizeInBits()-1 &&
TLI.getOperationAction(ISD::SINT_TO_FP, SrcVT) == TargetLowering::Custom){
// Do a signed conversion then adjust the result.
SDValue SignedConv = DAG.getNode(ISD::SINT_TO_FP, dl, DstVT, Op);
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 6c29c67..c7bf2d9 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -60,18 +60,6 @@ static SDVTList makeVTList(const EVT *VTs, unsigned NumVTs) {
return Res;
}
-static const fltSemantics *EVTToAPFloatSemantics(EVT VT) {
- switch (VT.getSimpleVT().SimpleTy) {
- default: llvm_unreachable("Unknown FP format");
- case MVT::f16: return &APFloat::IEEEhalf;
- case MVT::f32: return &APFloat::IEEEsingle;
- case MVT::f64: return &APFloat::IEEEdouble;
- case MVT::f80: return &APFloat::x87DoubleExtended;
- case MVT::f128: return &APFloat::IEEEquad;
- case MVT::ppcf128: return &APFloat::PPCDoubleDouble;
- }
-}
-
// Default null implementations of the callbacks.
void SelectionDAG::DAGUpdateListener::NodeDeleted(SDNode*, SDNode*) {}
void SelectionDAG::DAGUpdateListener::NodeUpdated(SDNode*) {}
@@ -95,7 +83,8 @@ bool ConstantFPSDNode::isValueValidForType(EVT VT,
// convert modifies in place, so make a copy.
APFloat Val2 = APFloat(Val);
bool losesInfo;
- (void) Val2.convert(*EVTToAPFloatSemantics(VT), APFloat::rmNearestTiesToEven,
+ (void) Val2.convert(SelectionDAG::EVTToAPFloatSemantics(VT),
+ APFloat::rmNearestTiesToEven,
&losesInfo);
return !losesInfo;
}
@@ -1081,7 +1070,7 @@ SDValue SelectionDAG::getConstantFP(double Val, EVT VT, bool isTarget) {
EltVT==MVT::f16) {
bool ignored;
APFloat apf = APFloat(Val);
- apf.convert(*EVTToAPFloatSemantics(EltVT), APFloat::rmNearestTiesToEven,
+ apf.convert(EVTToAPFloatSemantics(EltVT), APFloat::rmNearestTiesToEven,
&ignored);
return getConstantFP(apf, VT, isTarget);
} else
@@ -2442,7 +2431,8 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL,
return getConstant(Val.zextOrTrunc(VT.getSizeInBits()), VT);
case ISD::UINT_TO_FP:
case ISD::SINT_TO_FP: {
- APFloat apf(APInt::getNullValue(VT.getSizeInBits()));
+ APFloat apf(EVTToAPFloatSemantics(VT),
+ APInt::getNullValue(VT.getSizeInBits()));
(void)apf.convertFromAPInt(Val,
Opcode==ISD::SINT_TO_FP,
APFloat::rmNearestTiesToEven);
@@ -2450,9 +2440,9 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL,
}
case ISD::BITCAST:
if (VT == MVT::f32 && C->getValueType(0) == MVT::i32)
- return getConstantFP(APFloat(Val), VT);
+ return getConstantFP(APFloat(APFloat::IEEEsingle, Val), VT);
else if (VT == MVT::f64 && C->getValueType(0) == MVT::i64)
- return getConstantFP(APFloat(Val), VT);
+ return getConstantFP(APFloat(APFloat::IEEEdouble, Val), VT);
break;
case ISD::BSWAP:
return getConstant(Val.byteSwap(), VT);
@@ -2499,7 +2489,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL,
bool ignored;
// This can return overflow, underflow, or inexact; we don't care.
// FIXME need to be more flexible about rounding mode.
- (void)V.convert(*EVTToAPFloatSemantics(VT),
+ (void)V.convert(EVTToAPFloatSemantics(VT),
APFloat::rmNearestTiesToEven, &ignored);
return getConstantFP(V, VT);
}
@@ -3084,7 +3074,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT,
bool ignored;
// This can return overflow, underflow, or inexact; we don't care.
// FIXME need to be more flexible about rounding mode.
- (void)V.convert(*EVTToAPFloatSemantics(VT),
+ (void)V.convert(EVTToAPFloatSemantics(VT),
APFloat::rmNearestTiesToEven, &ignored);
return getConstantFP(V, VT);
}
@@ -3338,7 +3328,7 @@ static SDValue getMemsetValue(SDValue Value, EVT VT, SelectionDAG &DAG,
APInt Val = SplatByte(NumBits, C->getZExtValue() & 255);
if (VT.isInteger())
return DAG.getConstant(Val, VT);
- return DAG.getConstantFP(APFloat(Val), VT);
+ return DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(VT), Val), VT);
}
Value = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, Value);
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 8c22db3..b5f6907 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3693,7 +3693,8 @@ GetExponent(SelectionDAG &DAG, SDValue Op, const TargetLowering &TLI,
/// getF32Constant - Get 32-bit floating point constant.
static SDValue
getF32Constant(SelectionDAG &DAG, unsigned Flt) {
- return DAG.getConstantFP(APFloat(APInt(32, Flt)), MVT::f32);
+ return DAG.getConstantFP(APFloat(APFloat::IEEEsingle, APInt(32, Flt)),
+ MVT::f32);
}
/// expandExp - Lower an exp intrinsic. Handles the special sequences for
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp
index ef5f589..d68a0f4 100644
--- a/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -632,7 +632,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
else if (Op0->getType()->isDoubleTy())
GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth);
else if (Op0->getType()->isX86_FP80Ty()) {
- APFloat apf = APFloat(GV.IntVal);
+ APFloat apf = APFloat(APFloat::x87DoubleExtended, GV.IntVal);
uint64_t v;
bool ignored;
(void)apf.convertToInteger(&v, BitWidth,
@@ -751,27 +751,32 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
case Type::X86_FP80TyID:
case Type::PPC_FP128TyID:
case Type::FP128TyID: {
- APFloat apfLHS = APFloat(LHS.IntVal);
+ const fltSemantics &Sem = CE->getOperand(0)->getType()->getFltSemantics();
+ APFloat apfLHS = APFloat(Sem, LHS.IntVal);
switch (CE->getOpcode()) {
default: llvm_unreachable("Invalid long double opcode");
case Instruction::FAdd:
- apfLHS.add(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
+ apfLHS.add(APFloat(Sem, RHS.IntVal), APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
case Instruction::FSub:
- apfLHS.subtract(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
+ apfLHS.subtract(APFloat(Sem, RHS.IntVal),
+ APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
case Instruction::FMul:
- apfLHS.multiply(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
+ apfLHS.multiply(APFloat(Sem, RHS.IntVal),
+ APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
case Instruction::FDiv:
- apfLHS.divide(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
+ apfLHS.divide(APFloat(Sem, RHS.IntVal),
+ APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
case Instruction::FRem:
- apfLHS.mod(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
+ apfLHS.mod(APFloat(Sem, RHS.IntVal),
+ APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
}
diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp
index 103c0c0..53ea0a2 100644
--- a/lib/ExecutionEngine/JIT/JIT.cpp
+++ b/lib/ExecutionEngine/JIT/JIT.cpp
@@ -522,7 +522,8 @@ GenericValue JIT::runFunction(Function *F,
case Type::PPC_FP128TyID:
case Type::X86_FP80TyID:
case Type::FP128TyID:
- C = ConstantFP::get(F->getContext(), APFloat(AV.IntVal));
+ C = ConstantFP::get(F->getContext(), APFloat(ArgTy->getFltSemantics(),
+ AV.IntVal));
break;
case Type::PointerTyID:
void *ArgPtr = GVTOP(AV);
diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp
index 0ffb24e..417e0d1 100644
--- a/lib/IR/ConstantFold.cpp
+++ b/lib/IR/ConstantFold.cpp
@@ -168,8 +168,8 @@ static Constant *FoldBitCast(Constant *V, Type *DestTy) {
if (DestTy->isFloatingPointTy())
return ConstantFP::get(DestTy->getContext(),
- APFloat(CI->getValue(),
- !DestTy->isPPC_FP128Ty()));
+ APFloat(DestTy->getFltSemantics(),
+ CI->getValue()));
// Otherwise, can't fold this (vector?)
return 0;
@@ -647,8 +647,8 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
case Instruction::SIToFP:
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
APInt api = CI->getValue();
- APFloat apf(APInt::getNullValue(DestTy->getPrimitiveSizeInBits()),
- !DestTy->isPPC_FP128Ty() /* isEEEE */);
+ APFloat apf(DestTy->getFltSemantics(),
+ APInt::getNullValue(DestTy->getPrimitiveSizeInBits()));
(void)apf.convertFromAPInt(api,
opc==Instruction::SIToFP,
APFloat::rmNearestTiesToEven);
diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp
index 4b58599..c02fb98 100644
--- a/lib/IR/Constants.cpp
+++ b/lib/IR/Constants.cpp
@@ -108,7 +108,8 @@ Constant *Constant::getNullValue(Type *Ty) {
APFloat::getZero(APFloat::IEEEquad));
case Type::PPC_FP128TyID:
return ConstantFP::get(Ty->getContext(),
- APFloat(APInt::getNullValue(128)));
+ APFloat(APFloat::PPCDoubleDouble,
+ APInt::getNullValue(128)));
case Type::PointerTyID:
return ConstantPointerNull::get(cast<PointerType>(Ty));
case Type::StructTyID:
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 0e3c619..ee2fe5b 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -3032,7 +3032,7 @@ APFloat::initFromPPCDoubleDoubleAPInt(const APInt &api)
// Unless we have a special case, add in second double.
if (category == fcNormal) {
- APFloat v(APInt(64, i2));
+ APFloat v(IEEEdouble, APInt(64, i2));
fs = v.convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo);
assert(fs == opOK && !losesInfo);
(void)fs;
@@ -3185,27 +3185,43 @@ APFloat::initFromHalfAPInt(const APInt & api)
/// isIEEE argument distinguishes between PPC128 and IEEE128 (not meaningful
/// when the size is anything else).
void
-APFloat::initFromAPInt(const APInt& api, bool isIEEE)
+APFloat::initFromAPInt(const fltSemantics* Sem, const APInt& api)
{
- if (api.getBitWidth() == 16)
+ if (Sem == &IEEEhalf)
return initFromHalfAPInt(api);
- else if (api.getBitWidth() == 32)
+ if (Sem == &IEEEsingle)
return initFromFloatAPInt(api);
- else if (api.getBitWidth()==64)
+ if (Sem == &IEEEdouble)
return initFromDoubleAPInt(api);
- else if (api.getBitWidth()==80)
+ if (Sem == &x87DoubleExtended)
return initFromF80LongDoubleAPInt(api);
- else if (api.getBitWidth()==128)
- return (isIEEE ?
- initFromQuadrupleAPInt(api) : initFromPPCDoubleDoubleAPInt(api));
- else
- llvm_unreachable(0);
+ if (Sem == &IEEEquad)
+ return initFromQuadrupleAPInt(api);
+ if (Sem == &PPCDoubleDouble)
+ return initFromPPCDoubleDoubleAPInt(api);
+
+ llvm_unreachable(0);
}
APFloat
APFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE)
{
- return APFloat(APInt::getAllOnesValue(BitWidth), isIEEE);
+ switch (BitWidth) {
+ case 16:
+ return APFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth));
+ case 32:
+ return APFloat(IEEEsingle, APInt::getAllOnesValue(BitWidth));
+ case 64:
+ return APFloat(IEEEdouble, APInt::getAllOnesValue(BitWidth));
+ case 80:
+ return APFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth));
+ case 128:
+ if (isIEEE)
+ return APFloat(IEEEquad, APInt::getAllOnesValue(BitWidth));
+ return APFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth));
+ default:
+ llvm_unreachable("Unknown floating bit width");
+ }
}
APFloat APFloat::getLargest(const fltSemantics &Sem, bool Negative) {
@@ -3263,16 +3279,16 @@ APFloat APFloat::getSmallestNormalized(const fltSemantics &Sem, bool Negative) {
return Val;
}
-APFloat::APFloat(const APInt& api, bool isIEEE) {
- initFromAPInt(api, isIEEE);
+APFloat::APFloat(const fltSemantics &Sem, const APInt &API) {
+ initFromAPInt(&Sem, API);
}
APFloat::APFloat(float f) {
- initFromAPInt(APInt::floatToBits(f));
+ initFromAPInt(&IEEEsingle, APInt::floatToBits(f));
}
APFloat::APFloat(double d) {
- initFromAPInt(APInt::doubleToBits(d));
+ initFromAPInt(&IEEEdouble, APInt::doubleToBits(d));
}
namespace {
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 4b00b46..352c1d4 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -8015,9 +8015,11 @@ SDValue X86TargetLowering::LowerUINT_TO_FP_i64(SDValue Op,
SmallVector<Constant*,2> CV1;
CV1.push_back(
- ConstantFP::get(*Context, APFloat(APInt(64, 0x4330000000000000ULL))));
+ ConstantFP::get(*Context, APFloat(APFloat::IEEEdouble,
+ APInt(64, 0x4330000000000000ULL))));
CV1.push_back(
- ConstantFP::get(*Context, APFloat(APInt(64, 0x4530000000000000ULL))));
+ ConstantFP::get(*Context, APFloat(APFloat::IEEEdouble,
+ APInt(64, 0x4530000000000000ULL))));
Constant *C1 = ConstantVector::get(CV1);
SDValue CPIdx1 = DAG.getConstantPool(C1, getPointerTy(), 16);
@@ -8568,9 +8570,11 @@ SDValue X86TargetLowering::LowerFABS(SDValue Op, SelectionDAG &DAG) const {
}
Constant *C;
if (EltVT == MVT::f64)
- C = ConstantFP::get(*Context, APFloat(APInt(64, ~(1ULL << 63))));
+ C = ConstantFP::get(*Context, APFloat(APFloat::IEEEdouble,
+ APInt(64, ~(1ULL << 63))));
else
- C = ConstantFP::get(*Context, APFloat(APInt(32, ~(1U << 31))));
+ C = ConstantFP::get(*Context, APFloat(APFloat::IEEEsingle,
+ APInt(32, ~(1U << 31))));
C = ConstantVector::getSplat(NumElts, C);
SDValue CPIdx = DAG.getConstantPool(C, getPointerTy());
unsigned Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
@@ -8600,9 +8604,11 @@ SDValue X86TargetLowering::LowerFNEG(SDValue Op, SelectionDAG &DAG) const {
}
Constant *C;
if (EltVT == MVT::f64)
- C = ConstantFP::get(*Context, APFloat(APInt(64, 1ULL << 63)));
+ C = ConstantFP::get(*Context, APFloat(APFloat::IEEEdouble,
+ APInt(64, 1ULL << 63)));
else
- C = ConstantFP::get(*Context, APFloat(APInt(32, 1U << 31)));
+ C = ConstantFP::get(*Context, APFloat(APFloat::IEEEsingle,
+ APInt(32, 1U << 31)));
C = ConstantVector::getSplat(NumElts, C);
SDValue CPIdx = DAG.getConstantPool(C, getPointerTy());
unsigned Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
@@ -8646,13 +8652,15 @@ SDValue X86TargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
// First get the sign bit of second operand.
SmallVector<Constant*,4> CV;
if (SrcVT == MVT::f64) {
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(64, 1ULL << 63))));
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(64, 0))));
+ const fltSemantics &Sem = APFloat::IEEEdouble;
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem, APInt(64, 1ULL << 63))));
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem, APInt(64, 0))));
} else {
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 1U << 31))));
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0))));
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0))));
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0))));
+ const fltSemantics &Sem = APFloat::IEEEsingle;
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem, APInt(32, 1U << 31))));
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem, APInt(32, 0))));
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem, APInt(32, 0))));
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem, APInt(32, 0))));
}
Constant *C = ConstantVector::get(CV);
SDValue CPIdx = DAG.getConstantPool(C, getPointerTy(), 16);
@@ -8675,13 +8683,17 @@ SDValue X86TargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
// Clear first operand sign bit.
CV.clear();
if (VT == MVT::f64) {
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(64, ~(1ULL << 63)))));
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(64, 0))));
+ const fltSemantics &Sem = APFloat::IEEEdouble;
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem,
+ APInt(64, ~(1ULL << 63)))));
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem, APInt(64, 0))));
} else {
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, ~(1U << 31)))));
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0))));
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0))));
- CV.push_back(ConstantFP::get(*Context, APFloat(APInt(32, 0))));
+ const fltSemantics &Sem = APFloat::IEEEsingle;
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem,
+ APInt(32, ~(1U << 31)))));
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem, APInt(32, 0))));
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem, APInt(32, 0))));
+ CV.push_back(ConstantFP::get(*Context, APFloat(Sem, APInt(32, 0))));
}
C = ConstantVector::get(CV);
CPIdx = DAG.getConstantPool(C, getPointerTy(), 16);_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits