diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 0b6aca4ca34..9df930a6e3b 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -13040,13 +13040,6 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) { if (SDValue NewSel = foldBinOpIntoSelect(N)) return NewSel; - if ((Options.NoNaNsFPMath && Options.NoSignedZerosFPMath) || - (Flags.hasNoNaNs() && Flags.hasNoSignedZeros())) { - // fold (fmul A, 0) -> 0 - if (N1CFP && N1CFP->isZero()) - return N1; - } - if (Options.UnsafeFPMath || Flags.hasAllowReassociation()) { // fmul (fmul X, C1), C2 -> fmul X, C1 * C2 if (isConstantFPBuildVectorOrConstantFP(N1) && diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index eef467d116b..62d01fbf96c 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -7475,6 +7475,11 @@ SDValue SelectionDAG::simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y, if (YC->getValueAPF().isExactlyValue(1.0)) return X; + // X * 0.0 --> 0.0 + if (Opcode == ISD::FMUL && Flags.hasNoNaNs() && Flags.hasNoSignedZeros()) + if (YC->getValueAPF().isZero()) + return getConstantFP(0.0, SDLoc(Y), Y.getValueType()); + return SDValue(); } diff --git a/test/CodeGen/ARM/softfp-constant-comparison.ll b/test/CodeGen/ARM/softfp-constant-comparison.ll index 0b4e42843cb..e076e75e806 100644 --- a/test/CodeGen/ARM/softfp-constant-comparison.ll +++ b/test/CodeGen/ARM/softfp-constant-comparison.ll @@ -9,24 +9,13 @@ target triple = "thumbv7em-arm-none-eabi" define hidden void @fn1() nounwind #0 { ; CHECK-LABEL: fn1: ; CHECK: @ %bb.0: @ %entry -; CHECK-NEXT: .save {r7, lr} -; CHECK-NEXT: push {r7, lr} -; CHECK-NEXT: vldr d0, .LCPI0_0 -; CHECK-NEXT: vmov r0, r1, d0 -; CHECK-NEXT: mov r2, r0 -; CHECK-NEXT: mov r3, r1 -; CHECK-NEXT: bl __aeabi_dcmpeq +; CHECK-NEXT: movs r0, #1 ; CHECK-NEXT: cbnz r0, .LBB0_2 ; CHECK-NEXT: b .LBB0_1 ; CHECK-NEXT: .LBB0_1: @ %land.rhs ; CHECK-NEXT: b .LBB0_2 ; CHECK-NEXT: .LBB0_2: @ %land.end -; CHECK-NEXT: pop {r7, pc} -; CHECK-NEXT: .p2align 3 -; CHECK-NEXT: @ %bb.3: -; CHECK-NEXT: .LCPI0_0: -; CHECK-NEXT: .long 0 @ double 0 -; CHECK-NEXT: .long 0 +; CHECK-NEXT: bx lr entry: %0 = load i32, i32* @a, align 4 %conv = sitofp i32 %0 to double diff --git a/test/CodeGen/X86/fmul-combines.ll b/test/CodeGen/X86/fmul-combines.ll index 0c8a822e7ff..f9a3e75c3d7 100644 --- a/test/CodeGen/X86/fmul-combines.ll +++ b/test/CodeGen/X86/fmul-combines.ll @@ -261,3 +261,22 @@ define <4 x float> @fmul_fneg_fneg_v4f32(<4 x float> %x, <4 x float> %y) { %mul = fmul <4 x float> %x.neg, %y.neg ret <4 x float> %mul } + +; PR47517 - this could crash if we create 'fmul x, 0.0' nodes +; that do not constant fold in a particular order. + +define float @getNegatedExpression_crash(float* %p) { +; CHECK-LABEL: getNegatedExpression_crash: +; CHECK: # %bb.0: +; CHECK-NEXT: movl $0, (%rdi) +; CHECK-NEXT: xorps %xmm0, %xmm0 +; CHECK-NEXT: retq + store float 0.0, float* %p, align 1 + %real = load float, float* %p, align 1 + %r2 = fmul fast float %real, %real + %t1 = fmul fast float %real, 42.0 + %t2 = fmul fast float %real, %t1 + %mul_ac56 = fmul fast float %t2, %t1 + %mul_ac72 = fmul fast float %r2, %mul_ac56 + ret float %mul_ac72 +}