mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-28 06:24:57 +00:00
Change LegalFPImmediates to use APFloat.
Add APFloat interfaces to ConstantFP, SelectionDAG. Fix integer bit in double->APFloat conversion. Convert LegalizeDAG to use APFloat interface in ConstantFPSDNode uses. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41587 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -174,9 +174,14 @@ public:
|
|||||||
return getConstant(Val, VT, true);
|
return getConstant(Val, VT, true);
|
||||||
}
|
}
|
||||||
SDOperand getConstantFP(double Val, MVT::ValueType VT, bool isTarget = false);
|
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) {
|
SDOperand getTargetConstantFP(double Val, MVT::ValueType VT) {
|
||||||
return getConstantFP(Val, VT, true);
|
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,
|
SDOperand getGlobalAddress(const GlobalValue *GV, MVT::ValueType VT,
|
||||||
int offset = 0, bool isTargetGA = false);
|
int offset = 0, bool isTargetGA = false);
|
||||||
SDOperand getTargetGlobalAddress(const GlobalValue *GV, MVT::ValueType VT,
|
SDOperand getTargetGlobalAddress(const GlobalValue *GV, MVT::ValueType VT,
|
||||||
|
@ -1182,6 +1182,8 @@ public:
|
|||||||
}
|
}
|
||||||
bool isExactlyValue(const APFloat& V) const;
|
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 ConstantFPSDNode *) { return true; }
|
||||||
static bool classof(const SDNode *N) {
|
static bool classof(const SDNode *N) {
|
||||||
return N->getOpcode() == ISD::ConstantFP ||
|
return N->getOpcode() == ISD::ConstantFP ||
|
||||||
|
@ -218,12 +218,20 @@ class ConstantFP : public Constant {
|
|||||||
ConstantFP(const ConstantFP &); // DO NOT IMPLEMENT
|
ConstantFP(const ConstantFP &); // DO NOT IMPLEMENT
|
||||||
protected:
|
protected:
|
||||||
ConstantFP(const Type *Ty, double V);
|
ConstantFP(const Type *Ty, double V);
|
||||||
|
ConstantFP(const Type *Ty, const APFloat& V);
|
||||||
public:
|
public:
|
||||||
/// get() - Static factory methods - Return objects of the specified value
|
/// get() - Static factory methods - Return objects of the specified value
|
||||||
static ConstantFP *get(const Type *Ty, double V);
|
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.
|
/// 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 {
|
inline double getValue() const {
|
||||||
if (&Val.getSemantics() == &APFloat::IEEEdouble)
|
if (&Val.getSemantics() == &APFloat::IEEEdouble)
|
||||||
return Val.convertToDouble();
|
return Val.convertToDouble();
|
||||||
@ -232,6 +240,7 @@ public:
|
|||||||
else
|
else
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
inline const APFloat& getValueAPF() const { return Val; }
|
||||||
|
|
||||||
/// isNullValue - Return true if this is the value that would be returned by
|
/// 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
|
/// 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.
|
/// 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
|
/// As such, this method can be used to do an exact bit-for-bit comparison of
|
||||||
/// two floating point values.
|
/// 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:
|
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||||
static inline bool classof(const ConstantFP *) { return true; }
|
static inline bool classof(const ConstantFP *) { return true; }
|
||||||
static bool classof(const Value *V) {
|
static bool classof(const Value *V) {
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
||||||
#include "llvm/CodeGen/RuntimeLibcalls.h"
|
#include "llvm/CodeGen/RuntimeLibcalls.h"
|
||||||
|
#include "llvm/ADT/APFloat.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -220,7 +221,7 @@ public:
|
|||||||
unsigned &NumIntermediates,
|
unsigned &NumIntermediates,
|
||||||
MVT::ValueType &RegisterVT) const;
|
MVT::ValueType &RegisterVT) const;
|
||||||
|
|
||||||
typedef std::vector<double>::const_iterator legal_fpimm_iterator;
|
typedef std::vector<APFloat>::const_iterator legal_fpimm_iterator;
|
||||||
legal_fpimm_iterator legal_fpimm_begin() const {
|
legal_fpimm_iterator legal_fpimm_begin() const {
|
||||||
return LegalFPImmediates.begin();
|
return LegalFPImmediates.begin();
|
||||||
}
|
}
|
||||||
@ -781,8 +782,18 @@ protected:
|
|||||||
|
|
||||||
/// addLegalFPImmediate - Indicate that this target can instruction select
|
/// addLegalFPImmediate - Indicate that this target can instruction select
|
||||||
/// the specified FP immediate natively.
|
/// 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(Imm);
|
||||||
|
LegalFPImmediates.push_back(Immf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// setTargetDAGCombine - Targets should invoke this method for each target
|
/// setTargetDAGCombine - Targets should invoke this method for each target
|
||||||
@ -1118,7 +1129,7 @@ private:
|
|||||||
|
|
||||||
ValueTypeActionImpl ValueTypeActions;
|
ValueTypeActionImpl ValueTypeActions;
|
||||||
|
|
||||||
std::vector<double> LegalFPImmediates;
|
std::vector<APFloat> LegalFPImmediates;
|
||||||
|
|
||||||
std::vector<std::pair<MVT::ValueType,
|
std::vector<std::pair<MVT::ValueType,
|
||||||
TargetRegisterClass*> > AvailableRegClasses;
|
TargetRegisterClass*> > AvailableRegClasses;
|
||||||
|
@ -487,15 +487,15 @@ static SDOperand ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP,
|
|||||||
MVT::ValueType VT = CFP->getValueType(0);
|
MVT::ValueType VT = CFP->getValueType(0);
|
||||||
bool isDouble = VT == MVT::f64;
|
bool isDouble = VT == MVT::f64;
|
||||||
ConstantFP *LLVMC = ConstantFP::get(isDouble ? Type::DoubleTy :
|
ConstantFP *LLVMC = ConstantFP::get(isDouble ? Type::DoubleTy :
|
||||||
Type::FloatTy, CFP->getValue());
|
Type::FloatTy, CFP->getValueAPF());
|
||||||
if (!UseCP) {
|
if (!UseCP) {
|
||||||
double Val = LLVMC->getValue();
|
const APFloat& Val = LLVMC->getValueAPF();
|
||||||
return isDouble
|
return isDouble
|
||||||
? DAG.getConstant(DoubleToBits(Val), MVT::i64)
|
? DAG.getConstant(DoubleToBits(Val.convertToDouble()), MVT::i64)
|
||||||
: DAG.getConstant(FloatToBits(Val), MVT::i32);
|
: 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.
|
// Only do this if the target has a native EXTLOAD instruction from f32.
|
||||||
TLI.isLoadXLegal(ISD::EXTLOAD, MVT::f32)) {
|
TLI.isLoadXLegal(ISD::EXTLOAD, MVT::f32)) {
|
||||||
LLVMC = cast<ConstantFP>(ConstantExpr::getFPTrunc(LLVMC,Type::FloatTy));
|
LLVMC = cast<ConstantFP>(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 this is a legal constant, turn it into a TargetConstantFP node.
|
||||||
if (isLegal) {
|
if (isLegal) {
|
||||||
Result = DAG.getTargetConstantFP(CFP->getValue(), CFP->getValueType(0));
|
Result = DAG.getTargetConstantFP(CFP->getValueAPF(),
|
||||||
|
CFP->getValueType(0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1942,10 +1943,12 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
|||||||
// together.
|
// together.
|
||||||
if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(ST->getValue())) {
|
if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(ST->getValue())) {
|
||||||
if (CFP->getValueType(0) == MVT::f32) {
|
if (CFP->getValueType(0) == MVT::f32) {
|
||||||
Tmp3 = DAG.getConstant(FloatToBits(CFP->getValue()), MVT::i32);
|
Tmp3 = DAG.getConstant(FloatToBits(CFP->getValueAPF().
|
||||||
|
convertToFloat()), MVT::i32);
|
||||||
} else {
|
} else {
|
||||||
assert(CFP->getValueType(0) == MVT::f64 && "Unknown FP type!");
|
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(),
|
Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
|
||||||
SVOffset, isVolatile, Alignment);
|
SVOffset, isVolatile, Alignment);
|
||||||
@ -4212,7 +4215,7 @@ SDOperand SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
|
|||||||
for (unsigned i = 0, e = NumElems; i != e; ++i) {
|
for (unsigned i = 0, e = NumElems; i != e; ++i) {
|
||||||
if (ConstantFPSDNode *V =
|
if (ConstantFPSDNode *V =
|
||||||
dyn_cast<ConstantFPSDNode>(Node->getOperand(i))) {
|
dyn_cast<ConstantFPSDNode>(Node->getOperand(i))) {
|
||||||
CV.push_back(ConstantFP::get(OpNTy, V->getValue()));
|
CV.push_back(ConstantFP::get(OpNTy, V->getValueAPF()));
|
||||||
} else if (ConstantSDNode *V =
|
} else if (ConstantSDNode *V =
|
||||||
dyn_cast<ConstantSDNode>(Node->getOperand(i))) {
|
dyn_cast<ConstantSDNode>(Node->getOperand(i))) {
|
||||||
CV.push_back(ConstantInt::get(OpNTy, V->getValue()));
|
CV.push_back(ConstantInt::get(OpNTy, V->getValue()));
|
||||||
|
@ -52,6 +52,32 @@ bool ConstantFPSDNode::isExactlyValue(const APFloat& V) const {
|
|||||||
return Value.bitwiseIsEqual(V);
|
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
|
// ISD Namespace
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -669,18 +695,20 @@ SDOperand SelectionDAG::getConstant(uint64_t Val, MVT::ValueType VT, bool isT) {
|
|||||||
return SDOperand(N, 0);
|
return SDOperand(N, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDOperand SelectionDAG::getConstantFP(double Val, MVT::ValueType VT,
|
SDOperand SelectionDAG::getConstantFP(const APFloat& V, MVT::ValueType VT,
|
||||||
bool isTarget) {
|
bool isTarget) {
|
||||||
assert(MVT::isFloatingPoint(VT) && "Cannot create integer FP constant!");
|
assert(MVT::isFloatingPoint(VT) && "Cannot create integer FP constant!");
|
||||||
|
|
||||||
MVT::ValueType EltVT =
|
MVT::ValueType EltVT =
|
||||||
MVT::isVector(VT) ? MVT::getVectorElementType(VT) : VT;
|
MVT::isVector(VT) ? MVT::getVectorElementType(VT) : VT;
|
||||||
if (EltVT == MVT::f32)
|
bool isDouble = (EltVT == MVT::f64);
|
||||||
Val = (float)Val; // Mask out extra precision.
|
double Val = isDouble ? V.convertToDouble() : (double)V.convertToFloat();
|
||||||
|
|
||||||
// Do the map lookup using the actual bit pattern for the floating point
|
// 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
|
// value, so that we don't have problems with 0.0 comparing equal to -0.0, and
|
||||||
// we don't have issues with SNANs.
|
// we don't have issues with SNANs.
|
||||||
unsigned Opc = isTarget ? ISD::TargetConstantFP : ISD::ConstantFP;
|
unsigned Opc = isTarget ? ISD::TargetConstantFP : ISD::ConstantFP;
|
||||||
|
// ?? Should we store float/double/longdouble separately in ID?
|
||||||
FoldingSetNodeID ID;
|
FoldingSetNodeID ID;
|
||||||
AddNodeIDNode(ID, Opc, getVTList(EltVT), 0, 0);
|
AddNodeIDNode(ID, Opc, getVTList(EltVT), 0, 0);
|
||||||
ID.AddDouble(Val);
|
ID.AddDouble(Val);
|
||||||
@ -704,6 +732,16 @@ SDOperand SelectionDAG::getConstantFP(double Val, MVT::ValueType VT,
|
|||||||
return Result;
|
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,
|
SDOperand SelectionDAG::getGlobalAddress(const GlobalValue *GV,
|
||||||
MVT::ValueType VT, int Offset,
|
MVT::ValueType VT, int Offset,
|
||||||
bool isTargetGA) {
|
bool isTargetGA) {
|
||||||
|
@ -1617,7 +1617,7 @@ APFloat::APFloat(double d) {
|
|||||||
sign = mysign;
|
sign = mysign;
|
||||||
category = fcNormal;
|
category = fcNormal;
|
||||||
exponent = myexponent - 1023;
|
exponent = myexponent - 1023;
|
||||||
*significandParts() = mysignificand | 0x100000000000000LL;
|
*significandParts() = mysignificand | 0x10000000000000LL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,8 +142,8 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM)
|
|||||||
|
|
||||||
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
|
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
|
||||||
setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
|
setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
|
||||||
addLegalFPImmediate(+0.0); //F31
|
addLegalFPImmediate(APFloat(+0.0)); //F31
|
||||||
addLegalFPImmediate(-0.0); //-F31
|
addLegalFPImmediate(APFloat(-0.0)); //-F31
|
||||||
|
|
||||||
setJumpBufSize(272);
|
setJumpBufSize(272);
|
||||||
setJumpBufAlignment(16);
|
setJumpBufAlignment(16);
|
||||||
|
@ -121,8 +121,8 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM)
|
|||||||
computeRegisterProperties();
|
computeRegisterProperties();
|
||||||
|
|
||||||
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
|
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
|
||||||
addLegalFPImmediate(+0.0);
|
addLegalFPImmediate(APFloat(+0.0));
|
||||||
addLegalFPImmediate(+1.0);
|
addLegalFPImmediate(APFloat(+1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *IA64TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
const char *IA64TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||||
|
@ -296,7 +296,7 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
|||||||
// cases we handle.
|
// cases we handle.
|
||||||
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
|
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
|
||||||
setOperationAction(ISD::ConstantFP, MVT::f32, 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.
|
// Conversions to long double (in X87) go through memory.
|
||||||
setConvertAction(MVT::f32, MVT::f80, Expand);
|
setConvertAction(MVT::f32, MVT::f80, Expand);
|
||||||
@ -327,10 +327,10 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
|||||||
|
|
||||||
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
|
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
|
||||||
setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
|
setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
|
||||||
addLegalFPImmediate(+0.0); // FLD0
|
addLegalFPImmediate(APFloat(+0.0)); // FLD0
|
||||||
addLegalFPImmediate(+1.0); // FLD1
|
addLegalFPImmediate(APFloat(+1.0)); // FLD1
|
||||||
addLegalFPImmediate(-0.0); // FLD0/FCHS
|
addLegalFPImmediate(APFloat(-0.0)); // FLD0/FCHS
|
||||||
addLegalFPImmediate(-1.0); // FLD1/FCHS
|
addLegalFPImmediate(APFloat(-1.0)); // FLD1/FCHS
|
||||||
}
|
}
|
||||||
|
|
||||||
// Long double always uses X87.
|
// Long double always uses X87.
|
||||||
|
@ -240,15 +240,24 @@ ConstantInt *ConstantInt::get(const APInt& V) {
|
|||||||
|
|
||||||
|
|
||||||
ConstantFP::ConstantFP(const Type *Ty, double 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 {
|
bool ConstantFP::isNullValue() const {
|
||||||
return Val.isZero() && !Val.isNegative();
|
return Val.isZero() && !Val.isNegative();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConstantFP::isExactlyValue(double V) const {
|
bool ConstantFP::isExactlyValue(const APFloat& V) const {
|
||||||
return Val.bitwiseIsEqual(APFloat(V));
|
return Val.bitwiseIsEqual(V);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -289,14 +298,14 @@ ConstantFP *ConstantFP::get(const Type *Ty, double V) {
|
|||||||
DenseMapAPFloatKeyInfo::KeyTy Key(APFloat((float)V));
|
DenseMapAPFloatKeyInfo::KeyTy Key(APFloat((float)V));
|
||||||
ConstantFP *&Slot = (*FPConstants)[Key];
|
ConstantFP *&Slot = (*FPConstants)[Key];
|
||||||
if (Slot) return Slot;
|
if (Slot) return Slot;
|
||||||
return Slot = new ConstantFP(Ty, (float)V);
|
return Slot = new ConstantFP(Ty, APFloat((float)V));
|
||||||
} else if (Ty == Type::DoubleTy) {
|
} else if (Ty == Type::DoubleTy) {
|
||||||
// Without the redundant cast, the following is taken to be
|
// Without the redundant cast, the following is taken to be
|
||||||
// a function declaration. What a language.
|
// a function declaration. What a language.
|
||||||
DenseMapAPFloatKeyInfo::KeyTy Key(APFloat((double)V));
|
DenseMapAPFloatKeyInfo::KeyTy Key(APFloat((double)V));
|
||||||
ConstantFP *&Slot = (*FPConstants)[Key];
|
ConstantFP *&Slot = (*FPConstants)[Key];
|
||||||
if (Slot) return Slot;
|
if (Slot) return Slot;
|
||||||
return Slot = new ConstantFP(Ty, V);
|
return Slot = new ConstantFP(Ty, APFloat(V));
|
||||||
} else if (Ty == Type::X86_FP80Ty ||
|
} else if (Ty == Type::X86_FP80Ty ||
|
||||||
Ty == Type::PPC_FP128Ty || Ty == Type::FP128Ty) {
|
Ty == Type::PPC_FP128Ty || Ty == Type::FP128Ty) {
|
||||||
assert(0 && "Long double constants not handled yet.");
|
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
|
// ConstantXXX Classes
|
||||||
@ -699,14 +720,24 @@ bool ConstantInt::isValueValidForType(const Type *Ty, int64_t Val) {
|
|||||||
return (Val >= Min && Val <= Max);
|
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()) {
|
switch (Ty->getTypeID()) {
|
||||||
default:
|
default:
|
||||||
return false; // These can't be represented as floating point!
|
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:
|
case Type::FloatTyID:
|
||||||
|
return &Val2.getSemantics() == &APFloat::IEEEsingle ||
|
||||||
|
Val2.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven) ==
|
||||||
|
APFloat::opOK;
|
||||||
case Type::DoubleTyID:
|
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::X86_FP80TyID:
|
||||||
case Type::PPC_FP128TyID:
|
case Type::PPC_FP128TyID:
|
||||||
case Type::FP128TyID:
|
case Type::FP128TyID:
|
||||||
|
Reference in New Issue
Block a user