Index: lib/Target/AMDGPU/SIISelLowering.h =================================================================== --- lib/Target/AMDGPU/SIISelLowering.h +++ lib/Target/AMDGPU/SIISelLowering.h @@ -130,6 +130,8 @@ SDValue performXorCombine(SDNode *N, DAGCombinerInfo &DCI) const; SDValue performZeroExtendCombine(SDNode *N, DAGCombinerInfo &DCI) const; SDValue performClassCombine(SDNode *N, DAGCombinerInfo &DCI) const; + SDValue getCanonicalConstantFP(SelectionDAG &DAG, const SDLoc &SL, EVT VT, + const APFloat &C) const; SDValue performFCanonicalizeCombine(SDNode *N, DAGCombinerInfo &DCI) const; SDValue performFPMed3ImmCombine(SelectionDAG &DAG, const SDLoc &SL, Index: lib/Target/AMDGPU/SIISelLowering.cpp =================================================================== --- lib/Target/AMDGPU/SIISelLowering.cpp +++ lib/Target/AMDGPU/SIISelLowering.cpp @@ -6872,46 +6872,19 @@ } // Constant fold canonicalize. -SDValue SITargetLowering::performFCanonicalizeCombine( - SDNode *N, - DAGCombinerInfo &DCI) const { - SelectionDAG &DAG = DCI.DAG; - SDValue N0 = N->getOperand(0); - - // fcanonicalize undef -> qnan - if (N0.isUndef()) { - EVT VT = N->getValueType(0); - APFloat QNaN = APFloat::getQNaN(SelectionDAG::EVTToAPFloatSemantics(VT)); - return DAG.getConstantFP(QNaN, SDLoc(N), VT); - } - - ConstantFPSDNode *CFP = isConstOrConstSplatFP(N0); - if (!CFP) { - return isCanonicalized(DAG, N0) ? N0 : SDValue(); - } - - const APFloat &C = CFP->getValueAPF(); +SDValue SITargetLowering::getCanonicalConstantFP( + SelectionDAG &DAG, const SDLoc &SL, EVT VT, const APFloat &C) const { // Flush denormals to 0 if not enabled. - if (C.isDenormal()) { - EVT VT = N->getValueType(0); - EVT SVT = VT.getScalarType(); - if (SVT == MVT::f32 && !Subtarget->hasFP32Denormals()) - return DAG.getConstantFP(0.0, SDLoc(N), VT); - - if (SVT == MVT::f64 && !Subtarget->hasFP64Denormals()) - return DAG.getConstantFP(0.0, SDLoc(N), VT); - - if (SVT == MVT::f16 && !Subtarget->hasFP16Denormals()) - return DAG.getConstantFP(0.0, SDLoc(N), VT); - } + if (C.isDenormal() && !denormalsEnabledForType(VT)) + return DAG.getConstantFP(0.0, SL, VT); if (C.isNaN()) { - EVT VT = N->getValueType(0); APFloat CanonicalQNaN = APFloat::getQNaN(C.getSemantics()); if (C.isSignaling()) { // Quiet a signaling NaN. - return DAG.getConstantFP(CanonicalQNaN, SDLoc(N), VT); + // FIXME: Is this supposed to preserve payload bits? + return DAG.getConstantFP(CanonicalQNaN, SL, VT); } // Make sure it is the canonical NaN bitpattern. @@ -6919,10 +6892,32 @@ // TODO: Can we use -1 as the canonical NaN value since it's an inline // immediate? if (C.bitcastToAPInt() != CanonicalQNaN.bitcastToAPInt()) - return DAG.getConstantFP(CanonicalQNaN, SDLoc(N), VT); + return DAG.getConstantFP(CanonicalQNaN, SL, VT); + } + + // Already canonical. + return DAG.getConstantFP(C, SL, VT); +} + +SDValue SITargetLowering::performFCanonicalizeCombine( + SDNode *N, + DAGCombinerInfo &DCI) const { + SelectionDAG &DAG = DCI.DAG; + SDValue N0 = N->getOperand(0); + + // fcanonicalize undef -> qnan + if (N0.isUndef()) { + EVT VT = N->getValueType(0); + APFloat QNaN = APFloat::getQNaN(SelectionDAG::EVTToAPFloatSemantics(VT)); + return DAG.getConstantFP(QNaN, SDLoc(N), VT); + } + + if (ConstantFPSDNode *CFP = isConstOrConstSplatFP(N0)) { + EVT VT = N->getValueType(0); + return getCanonicalConstantFP(DAG, SDLoc(N), VT, CFP->getValueAPF()); } - return N0; + return isCanonicalized(DAG, N0) ? N0 : SDValue(); } static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc) {