Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4438,28 +4438,37 @@ N1.getValueType() == VT && "Binary operator types must match!"); break; case ISD::FADD: + if (getTarget().Options.UnsafeFPMath || + Flags.hasNoSignedZeros()) { + // x+0 --> x + if (N2CFP && N2CFP->getValueAPF().isZero()) + return N1; + } + assert(VT.isFloatingPoint() && "This operator only applies to FP types!"); + assert(N1.getValueType() == N2.getValueType() && + N1.getValueType() == VT && "Binary operator types must match!"); + break; case ISD::FSUB: + // x-0 --> x + if (N2CFP && N2CFP->getValueAPF().isZero()) { + return N1; + } + assert(VT.isFloatingPoint() && "This operator only applies to FP types!"); + assert(N1.getValueType() == N2.getValueType() && + N1.getValueType() == VT && "Binary operator types must match!"); + break; case ISD::FMUL: + if (getTarget().Options.UnsafeFPMath || + (Flags.hasNoNaNs() && Flags.hasNoSignedZeros())) { + // x*0 --> 0 + if (N2CFP && N2CFP->isZero()) + return N2; + } else if (N2CFP && N2CFP->isExactlyValue(1.0)) { + // x*1 --> x + return N1; + } case ISD::FDIV: case ISD::FREM: - if (getTarget().Options.UnsafeFPMath) { - if (Opcode == ISD::FADD) { - // x+0 --> x - if (N2CFP && N2CFP->getValueAPF().isZero()) - return N1; - } else if (Opcode == ISD::FSUB) { - // x-0 --> x - if (N2CFP && N2CFP->getValueAPF().isZero()) - return N1; - } else if (Opcode == ISD::FMUL) { - // x*0 --> 0 - if (N2CFP && N2CFP->isZero()) - return N2; - // x*1 --> x - if (N2CFP && N2CFP->isExactlyValue(1.0)) - return N1; - } - } assert(VT.isFloatingPoint() && "This operator only applies to FP types!"); assert(N1.getValueType() == N2.getValueType() && N1.getValueType() == VT && "Binary operator types must match!"); Index: test/CodeGen/X86/fp-fold.ll =================================================================== --- test/CodeGen/X86/fp-fold.ll +++ test/CodeGen/X86/fp-fold.ll @@ -0,0 +1,62 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefixes=ANY,STRICT +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -enable-unsafe-fp-math | FileCheck %s --check-prefixes=ANY,UNSAFE + +; This is duplicated from tests for InstSimplify. If you're +; adding something here, you should probably add it there too. + +define float @fadd_zero_1(float %x) { +; ANY-LABEL: fadd_zero_1: +; ANY: # %bb.0: +; ANY-NEXT: retq + %r = fadd nsz float %x, 0.0 + ret float %r +} + +define float @fadd_zero_2(float %x) { +; ANY-LABEL: fadd_zero_2: +; ANY: # %bb.0: +; ANY-NEXT: retq + %r = fadd nsz float %x, -0.0 + ret float %r +} + +define float @fsub_zero_1(float %x) { +; ANY-LABEL: fsub_zero_1: +; ANY: # %bb.0: +; ANY-NEXT: retq + %r = fsub float %x, 0.0 + ret float %r +} + +define float @fsub_zero_2(float %x) { +; ANY-LABEL: fsub_zero_2: +; ANY: # %bb.0: +; ANY-NEXT: retq + %r = fsub float %x, -0.0 + ret float %r +} + +; TODO: handle x*0 for fast flags the same as unsafe +define float @fmul_zero(float %x) { +; STRICT-LABEL: fmul_zero: +; STRICT: # %bb.0: +; STRICT: xorps %xmm1, %xmm1 +; STRICT: mulss %xmm1, %xmm0 +; STRICT-NEXT: retq +; +; UNSAFE-LABEL: fmul_zero: +; UNSAFE: # %bb.0: +; UNSAFE: xorps %xmm0, %xmm0 +; UNSAFE-NEXT: retq + %r = fmul nnan nsz float %x, 0.0 + ret float %r +} + +define float @fmul_one(float %x) { +; ANY-LABEL: fmul_one: +; ANY: # %bb.0: +; ANY-NEXT: retq + %r = fmul float %x, 1.0 + ret float %r +}