Index: include/llvm/Target/TargetLowering.h =================================================================== --- include/llvm/Target/TargetLowering.h +++ include/llvm/Target/TargetLowering.h @@ -1861,6 +1861,12 @@ return false; } + /// Return true if a given fpext operation is free. This form allows the + /// target to filter to only allow for specific users where this is free. + virtual bool isFPExtFree(SDValue UseOp, EVT VT) const { + return isFPExtFree(VT); + } + /// Return true if folding a vector load into ExtVal (a sign, zero, or any /// extend node) is profitable. virtual bool isVectorLoadExtDesirable(SDValue ExtVal) const { return false; } Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -8372,7 +8372,6 @@ // Always prefer FMAD to FMA for precision. unsigned PreferredFusedOpcode = HasFMAD ? ISD::FMAD : ISD::FMA; bool Aggressive = TLI.enableAggressiveFMAFusion(VT); - bool LookThroughFPExt = TLI.isFPExtFree(VT); // If we have two choices trying to fold (fadd (fmul u, v), (fmul x, y)), // prefer to fold the multiply with fewer uses. @@ -8398,9 +8397,9 @@ } // Look through FP_EXTEND nodes to do more combining. - if (AllowFusion && LookThroughFPExt) { + if (AllowFusion) { // fold (fadd (fpext (fmul x, y)), z) -> (fma (fpext x), (fpext y), z) - if (N0.getOpcode() == ISD::FP_EXTEND) { + if (N0.getOpcode() == ISD::FP_EXTEND && TLI.isFPExtFree(N0, VT)) { SDValue N00 = N0.getOperand(0); if (N00.getOpcode() == ISD::FMUL) return DAG.getNode(PreferredFusedOpcode, SL, VT, @@ -8412,7 +8411,7 @@ // fold (fadd x, (fpext (fmul y, z))) -> (fma (fpext y), (fpext z), x) // Note: Commutes FADD operands. - if (N1.getOpcode() == ISD::FP_EXTEND) { + if (N1.getOpcode() == ISD::FP_EXTEND && TLI.isFPExtFree(N1, VT)) { SDValue N10 = N1.getOperand(0); if (N10.getOpcode() == ISD::FMUL) return DAG.getNode(PreferredFusedOpcode, SL, VT, @@ -8455,7 +8454,7 @@ N0)); } - if (AllowFusion && LookThroughFPExt) { + if (AllowFusion) { // fold (fadd (fma x, y, (fpext (fmul u, v))), z) // -> (fma x, y, (fma (fpext u), (fpext v), z)) auto FoldFAddFMAFPExtFMul = [&] ( @@ -8468,7 +8467,7 @@ }; if (N0.getOpcode() == PreferredFusedOpcode) { SDValue N02 = N0.getOperand(2); - if (N02.getOpcode() == ISD::FP_EXTEND) { + if (N02.getOpcode() == ISD::FP_EXTEND && TLI.isFPExtFree(N02, VT)) { SDValue N020 = N02.getOperand(0); if (N020.getOpcode() == ISD::FMUL) return FoldFAddFMAFPExtFMul(N0.getOperand(0), N0.getOperand(1), @@ -8567,7 +8566,6 @@ // Always prefer FMAD to FMA for precision. unsigned PreferredFusedOpcode = HasFMAD ? ISD::FMAD : ISD::FMA; bool Aggressive = TLI.enableAggressiveFMAFusion(VT); - bool LookThroughFPExt = TLI.isFPExtFree(VT); // fold (fsub (fmul x, y), z) -> (fma x, y, (fneg z)) if (N0.getOpcode() == ISD::FMUL && @@ -8598,10 +8596,10 @@ } // Look through FP_EXTEND nodes to do more combining. - if (AllowFusion && LookThroughFPExt) { + if (AllowFusion) { // fold (fsub (fpext (fmul x, y)), z) // -> (fma (fpext x), (fpext y), (fneg z)) - if (N0.getOpcode() == ISD::FP_EXTEND) { + if (N0.getOpcode() == ISD::FP_EXTEND && TLI.isFPExtFree(N0, VT)) { SDValue N00 = N0.getOperand(0); if (N00.getOpcode() == ISD::FMUL) return DAG.getNode(PreferredFusedOpcode, SL, VT, @@ -8711,12 +8709,12 @@ N21, N0)); } - if (AllowFusion && LookThroughFPExt) { + if (AllowFusion) { // fold (fsub (fma x, y, (fpext (fmul u, v))), z) // -> (fma x, y (fma (fpext u), (fpext v), (fneg z))) if (N0.getOpcode() == PreferredFusedOpcode) { SDValue N02 = N0.getOperand(2); - if (N02.getOpcode() == ISD::FP_EXTEND) { + if (N02.getOpcode() == ISD::FP_EXTEND && TLI.isFPExtFree(N02, VT)) { SDValue N020 = N02.getOperand(0); if (N020.getOpcode() == ISD::FMUL) return DAG.getNode(PreferredFusedOpcode, SL, VT,