return V;
}
+SDValue SelectionDAG::foldConstantFPMath(unsigned Opcode, const SDLoc &DL,
+ EVT VT, SDValue N1, SDValue N2) {
+ auto *N1CFP = dyn_cast<ConstantFPSDNode>(N1.getNode());
+ auto *N2CFP = dyn_cast<ConstantFPSDNode>(N2.getNode());
+ bool HasFPExceptions = TLI->hasFloatingPointExceptions();
+ if (N1CFP && N2CFP) {
+ APFloat C1 = N1CFP->getValueAPF(), C2 = N2CFP->getValueAPF();
+ APFloat::opStatus Status;
+ switch (Opcode) {
+ case ISD::FADD:
+ Status = C1.add(C2, APFloat::rmNearestTiesToEven);
+ if (!HasFPExceptions || Status != APFloat::opInvalidOp)
+ return getConstantFP(C1, DL, VT);
+ break;
+ case ISD::FSUB:
+ Status = C1.subtract(C2, APFloat::rmNearestTiesToEven);
+ if (!HasFPExceptions || Status != APFloat::opInvalidOp)
+ return getConstantFP(C1, DL, VT);
+ break;
+ case ISD::FMUL:
+ Status = C1.multiply(C2, APFloat::rmNearestTiesToEven);
+ if (!HasFPExceptions || Status != APFloat::opInvalidOp)
+ return getConstantFP(C1, DL, VT);
+ break;
+ case ISD::FDIV:
+ Status = C1.divide(C2, APFloat::rmNearestTiesToEven);
+ if (!HasFPExceptions || (Status != APFloat::opInvalidOp &&
+ Status != APFloat::opDivByZero)) {
+ return getConstantFP(C1, DL, VT);
+ }
+ break;
+ case ISD::FREM:
+ Status = C1.mod(C2);
+ if (!HasFPExceptions || (Status != APFloat::opInvalidOp &&
+ Status != APFloat::opDivByZero)) {
+ return getConstantFP(C1, DL, VT);
+ }
+ break;
+ case ISD::FCOPYSIGN:
+ C1.copySign(C2);
+ return getConstantFP(C1, DL, VT);
+ default: break;
+ }
+ }
+ if (N1CFP && Opcode == ISD::FP_ROUND) {
+ APFloat C1 = N1CFP->getValueAPF(); // make copy
+ bool Unused;
+ // This can return overflow, underflow, or inexact; we don't care.
+ // FIXME need to be more flexible about rounding mode.
+ (void) C1.convert(EVTToAPFloatSemantics(VT), APFloat::rmNearestTiesToEven,
+ &Unused);
+ return getConstantFP(C1, DL, VT);
+ }
+
+ switch (Opcode) {
+ case ISD::FADD:
+ case ISD::FSUB:
+ case ISD::FMUL:
+ case ISD::FDIV:
+ case ISD::FREM:
+ // If both operands are undef, the result is undef. If 1 operand is undef,
+ // the result is NaN. This should match the behavior of the IR optimizer.
+ if (N1.isUndef() && N2.isUndef())
+ return getUNDEF(VT);
+ if (N1.isUndef() || N2.isUndef())
+ return getConstantFP(APFloat::getNaN(EVTToAPFloatSemantics(VT)), DL, VT);
+ }
+ return SDValue();
+}
+
SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
SDValue N1, SDValue N2, const SDNodeFlags Flags) {
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
FoldConstantArithmetic(Opcode, DL, VT, N1.getNode(), N2.getNode()))
return SV;
- // Constant fold FP operations.
- bool HasFPExceptions = TLI->hasFloatingPointExceptions();
- if (N1CFP) {
- if (N2CFP) {
- APFloat V1 = N1CFP->getValueAPF(), V2 = N2CFP->getValueAPF();
- APFloat::opStatus s;
- switch (Opcode) {
- case ISD::FADD:
- s = V1.add(V2, APFloat::rmNearestTiesToEven);
- if (!HasFPExceptions || s != APFloat::opInvalidOp)
- return getConstantFP(V1, DL, VT);
- break;
- case ISD::FSUB:
- s = V1.subtract(V2, APFloat::rmNearestTiesToEven);
- if (!HasFPExceptions || s!=APFloat::opInvalidOp)
- return getConstantFP(V1, DL, VT);
- break;
- case ISD::FMUL:
- s = V1.multiply(V2, APFloat::rmNearestTiesToEven);
- if (!HasFPExceptions || s!=APFloat::opInvalidOp)
- return getConstantFP(V1, DL, VT);
- break;
- case ISD::FDIV:
- s = V1.divide(V2, APFloat::rmNearestTiesToEven);
- if (!HasFPExceptions || (s!=APFloat::opInvalidOp &&
- s!=APFloat::opDivByZero)) {
- return getConstantFP(V1, DL, VT);
- }
- break;
- case ISD::FREM :
- s = V1.mod(V2);
- if (!HasFPExceptions || (s!=APFloat::opInvalidOp &&
- s!=APFloat::opDivByZero)) {
- return getConstantFP(V1, DL, VT);
- }
- break;
- case ISD::FCOPYSIGN:
- V1.copySign(V2);
- return getConstantFP(V1, DL, VT);
- default: break;
- }
- }
-
- if (Opcode == ISD::FP_ROUND) {
- APFloat V = N1CFP->getValueAPF(); // make copy
- 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),
- APFloat::rmNearestTiesToEven, &ignored);
- return getConstantFP(V, DL, VT);
- }
- }
-
- switch (Opcode) {
- case ISD::FADD:
- case ISD::FSUB:
- case ISD::FMUL:
- case ISD::FDIV:
- case ISD::FREM:
- // If both operands are undef, the result is undef. If 1 operand is undef,
- // the result is NaN. This should match the behavior of the IR optimizer.
- if (N1.isUndef() && N2.isUndef())
- return getUNDEF(VT);
- if (N1.isUndef() || N2.isUndef())
- return getConstantFP(APFloat::getNaN(EVTToAPFloatSemantics(VT)), DL, VT);
- }
+ if (SDValue V = foldConstantFPMath(Opcode, DL, VT, N1, N2))
+ return V;
// Canonicalize an UNDEF to the RHS, even over a constant.
if (N1.isUndef()) {