diff options
author | Dale Johannesen <dalej@apple.com> | 2007-08-31 23:34:27 +0000 |
---|---|---|
committer | Dale Johannesen <dalej@apple.com> | 2007-08-31 23:34:27 +0000 |
commit | 7604c1b5a616eccc909ae58daa6e7afd54fa2d71 (patch) | |
tree | ac0eb685f19e086a27ab59d3fe86795fec4fc977 /lib/CodeGen | |
parent | ce77c41ada8d0ebe75d6e45d520314b72f4be260 (diff) | |
download | external_llvm-7604c1b5a616eccc909ae58daa6e7afd54fa2d71.tar.gz external_llvm-7604c1b5a616eccc909ae58daa6e7afd54fa2d71.tar.bz2 external_llvm-7604c1b5a616eccc909ae58daa6e7afd54fa2d71.zip |
Add mod, copysign, abs operations to APFloat.
Implement some constant folding in SelectionDAG and
DAGCombiner using APFloat. Remove double versions
of constructor and getValue from ConstantFPSDNode.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41664 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 16 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 88 |
2 files changed, 67 insertions, 37 deletions
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 0514bc181b..dae4e2102d 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -410,9 +410,11 @@ static SDOperand GetNegatedExpression(SDOperand Op, SelectionDAG &DAG, assert(Depth <= 6 && "GetNegatedExpression doesn't match isNegatibleForFree"); switch (Op.getOpcode()) { default: assert(0 && "Unknown code"); - case ISD::ConstantFP: - return DAG.getConstantFP(-cast<ConstantFPSDNode>(Op)->getValue(), - Op.getValueType()); + case ISD::ConstantFP: { + APFloat V = cast<ConstantFPSDNode>(Op)->getValueAPF(); + V.changeSign(); + return DAG.getConstantFP(V, Op.getValueType()); + } case ISD::FADD: // FIXME: determine better conditions for this xform. assert(UnsafeFPMath); @@ -432,7 +434,7 @@ static SDOperand GetNegatedExpression(SDOperand Op, SelectionDAG &DAG, // -(0-B) -> B if (ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(Op.getOperand(0))) - if (N0CFP->getValue() == 0.0) + if (N0CFP->getValueAPF().isZero()) return Op.getOperand(1); // -(A-B) -> B-A @@ -3080,7 +3082,7 @@ SDOperand DAGCombiner::visitFSUB(SDNode *N) { if (N0CFP && N1CFP) return DAG.getNode(ISD::FSUB, VT, N0, N1); // fold (0-B) -> -B - if (UnsafeFPMath && N0CFP && N0CFP->getValue() == 0.0) { + if (UnsafeFPMath && N0CFP && N0CFP->getValueAPF().isZero()) { if (isNegatibleForFree(N1)) return GetNegatedExpression(N1, DAG); return DAG.getNode(ISD::FNEG, VT, N1); @@ -3304,7 +3306,7 @@ SDOperand DAGCombiner::visitFP_ROUND_INREG(SDNode *N) { // fold (fp_round_inreg c1fp) -> c1fp if (N0CFP) { - SDOperand Round = DAG.getConstantFP(N0CFP->getValue(), EVT); + SDOperand Round = DAG.getConstantFP(N0CFP->getValueAPF(), EVT); return DAG.getNode(ISD::FP_EXTEND, VT, Round); } return SDOperand(); @@ -4207,7 +4209,7 @@ SDOperand DAGCombiner::SimplifyVBinOp(SDNode *N) { if ((RHSOp.getOpcode() == ISD::Constant && cast<ConstantSDNode>(RHSOp.Val)->isNullValue()) || (RHSOp.getOpcode() == ISD::ConstantFP && - !cast<ConstantFPSDNode>(RHSOp.Val)->getValue())) + cast<ConstantFPSDNode>(RHSOp.Val)->getValueAPF().isZero())) break; } Ops.push_back(DAG.getNode(N->getOpcode(), EltType, LHSOp, RHSOp)); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 156c73959f..05d5ec0ec2 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -727,7 +727,8 @@ SDOperand SelectionDAG::getConstantFP(const APFloat& V, MVT::ValueType VT, if (!MVT::isVector(VT)) return SDOperand(N, 0); if (!N) { - N = new ConstantFPSDNode(isTarget, Val, EltVT); + N = new ConstantFPSDNode(isTarget, + isDouble ? APFloat(Val) : APFloat((float)Val), EltVT); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); } @@ -1665,27 +1666,44 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, } } - // Constant fold unary operations with an floating point constant operand. - if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Operand.Val)) + // Constant fold unary operations with a floating point constant operand. + if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Operand.Val)) { + APFloat V = C->getValueAPF(); // make copy switch (Opcode) { case ISD::FNEG: - return getConstantFP(-C->getValue(), VT); + V.changeSign(); + return getConstantFP(V, VT); case ISD::FABS: - return getConstantFP(fabs(C->getValue()), VT); + V.clearSign(); + return getConstantFP(V, VT); case ISD::FP_ROUND: case ISD::FP_EXTEND: - return getConstantFP(C->getValue(), VT); + // This can return overflow, underflow, or inexact; we don't care. + // FIXME need to be more flexible about rounding mode. + (void) V.convert(VT==MVT::f32 ? APFloat::IEEEsingle : + APFloat::IEEEdouble, + APFloat::rmNearestTiesToEven); + return getConstantFP(V, VT); case ISD::FP_TO_SINT: - return getConstant((int64_t)C->getValue(), VT); - case ISD::FP_TO_UINT: - return getConstant((uint64_t)C->getValue(), VT); + case ISD::FP_TO_UINT: { + integerPart x; + assert(integerPartWidth >= 64); + // FIXME need to be more flexible about rounding mode. + APFloat::opStatus s = V.convertToInteger(&x, 64U, + Opcode==ISD::FP_TO_SINT, + APFloat::rmTowardZero); + if (s==APFloat::opInvalidOp) // inexact is OK, in fact usual + break; + return getConstant(x, VT); + } case ISD::BIT_CONVERT: if (VT == MVT::i32 && C->getValueType(0) == MVT::f32) - return getConstant(FloatToBits(C->getValue()), VT); + return getConstant(FloatToBits(V.convertToFloat()), VT); else if (VT == MVT::i64 && C->getValueType(0) == MVT::f64) - return getConstant(DoubleToBits(C->getValue()), VT); + return getConstant(DoubleToBits(V.convertToDouble()), VT); break; } + } unsigned OpOpcode = Operand.Val->getOpcode(); switch (Opcode) { @@ -1914,29 +1932,37 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, ConstantFPSDNode *N2CFP = dyn_cast<ConstantFPSDNode>(N2.Val); if (N1CFP) { if (N2CFP) { - double C1 = N1CFP->getValue(), C2 = N2CFP->getValue(); + APFloat V1 = N1CFP->getValueAPF(), V2 = N2CFP->getValueAPF(); + APFloat::opStatus s; switch (Opcode) { - case ISD::FADD: return getConstantFP(C1 + C2, VT); - case ISD::FSUB: return getConstantFP(C1 - C2, VT); - case ISD::FMUL: return getConstantFP(C1 * C2, VT); + case ISD::FADD: + s = V1.add(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp) + return getConstantFP(V1, VT); + break; + case ISD::FSUB: + s = V1.subtract(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp) + return getConstantFP(V1, VT); + break; + case ISD::FMUL: + s = V1.multiply(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp) + return getConstantFP(V1, VT); + break; case ISD::FDIV: - if (C2) return getConstantFP(C1 / C2, VT); + s = V1.divide(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp && s!=APFloat::opDivByZero) + return getConstantFP(V1, VT); break; case ISD::FREM : - if (C2) return getConstantFP(fmod(C1, C2), VT); + s = V1.mod(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp && s!=APFloat::opDivByZero) + return getConstantFP(V1, VT); break; - case ISD::FCOPYSIGN: { - union { - double F; - uint64_t I; - } u1; - u1.F = C1; - if (int64_t(DoubleToBits(C2)) < 0) // Sign bit of RHS set? - u1.I |= 1ULL << 63; // Set the sign bit of the LHS. - else - u1.I &= (1ULL << 63)-1; // Clear the sign bit of the LHS. - return getConstantFP(u1.F, VT); - } + case ISD::FCOPYSIGN: + V1.copySign(V2); + return getConstantFP(V1, VT); default: break; } } else { // Cannonicalize constant to RHS if commutative @@ -3688,7 +3714,9 @@ 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->getValue() << ">"; + cerr << "<" << (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEsingle ? + CSDN->getValueAPF().convertToFloat() : + CSDN->getValueAPF().convertToDouble()) << ">"; } else if (const GlobalAddressSDNode *GADN = dyn_cast<GlobalAddressSDNode>(this)) { int offset = GADN->getOffset(); |