diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -13217,10 +13217,11 @@ EVT VT = N->getValueType(0); SDLoc DL(N); const TargetOptions &Options = DAG.getTarget().Options; + // FMA nodes have flags that propagate to the created nodes. SelectionDAG::FlagInserter FlagsInserter(DAG, N); - // FMA nodes have flags that propagate to the created nodes. - bool UnsafeFPMath = Options.UnsafeFPMath || isContractable(N); + bool UnsafeFPMath = + Options.UnsafeFPMath || N->getFlags().hasAllowReassociation(); // Constant fold FMA. if (isa(N0) && diff --git a/llvm/test/CodeGen/PowerPC/fma-combine.ll b/llvm/test/CodeGen/PowerPC/fma-combine.ll --- a/llvm/test/CodeGen/PowerPC/fma-combine.ll +++ b/llvm/test/CodeGen/PowerPC/fma-combine.ll @@ -313,5 +313,37 @@ ret <2 x double> %0 } +define double @fma_combine_const(double %a, double %b) { +; CHECK-FAST-LABEL: fma_combine_const: +; CHECK-FAST: # %bb.0: # %entry +; CHECK-FAST-NEXT: addis 3, 2, .LCPI9_0@toc@ha +; CHECK-FAST-NEXT: lfd 0, .LCPI9_0@toc@l(3) +; CHECK-FAST-NEXT: xsmaddadp 2, 1, 0 +; CHECK-FAST-NEXT: fmr 1, 2 +; CHECK-FAST-NEXT: blr +; +; CHECK-FAST-NOVSX-LABEL: fma_combine_const: +; CHECK-FAST-NOVSX: # %bb.0: # %entry +; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI9_0@toc@ha +; CHECK-FAST-NOVSX-NEXT: lfd 0, .LCPI9_0@toc@l(3) +; CHECK-FAST-NOVSX-NEXT: fmadd 1, 1, 0, 2 +; CHECK-FAST-NOVSX-NEXT: blr +; +; CHECK-LABEL: fma_combine_const: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: addis 3, 2, .LCPI9_0@toc@ha +; CHECK-NEXT: lfd 0, .LCPI9_0@toc@l(3) +; CHECK-NEXT: addis 3, 2, .LCPI9_1@toc@ha +; CHECK-NEXT: lfd 3, .LCPI9_1@toc@l(3) +; CHECK-NEXT: xsmuldp 0, 1, 0 +; CHECK-NEXT: fmr 1, 2 +; CHECK-NEXT: xsmaddadp 1, 0, 3 +; CHECK-NEXT: blr +entry: + %0 = fmul double %a, 1.1 + %1 = call contract double @llvm.fma.f64(double %0, double 2.1, double %b) + ret double %1 +} + declare double @llvm.fma.f64(double, double, double) nounwind readnone declare <2 x double> @llvm.fma.v2f64(<2 x double>, <2 x double>, <2 x double>) nounwind readnone diff --git a/llvm/test/CodeGen/X86/fma-scalar-combine.ll b/llvm/test/CodeGen/X86/fma-scalar-combine.ll --- a/llvm/test/CodeGen/X86/fma-scalar-combine.ll +++ b/llvm/test/CodeGen/X86/fma-scalar-combine.ll @@ -542,3 +542,19 @@ %8 = insertelement <2 x double> %c, double %7, i64 0 ret <2 x double> %8 } + +; Don't fold into (fmul x, c1+c2) if reassoc not set +define float @fma_const_fmul(float %x) { +; CHECK-LABEL: fma_const_fmul: +; CHECK: # %bb.0: +; CHECK-NEXT: vmulss {{.*}}(%rip), %xmm0, %xmm1 # EVEX TO VEX Compression encoding: [0xc5,0xfa,0x59,0x0d,A,A,A,A] +; CHECK-NEXT: # fixup A - offset: 4, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; CHECK-NEXT: vfmadd132ss {{.*}}(%rip), %xmm1, %xmm0 # EVEX TO VEX Compression encoding: [0xc4,0xe2,0x71,0x99,0x05,A,A,A,A] +; CHECK-NEXT: # fixup A - offset: 5, value: {{\.LCPI.*}}-4, kind: reloc_riprel_4byte +; CHECK-NEXT: # xmm0 = (xmm0 * mem) + xmm1 +; CHECK-NEXT: retq # encoding: [0xc3] + %mul1 = fmul contract float %x, 10.0 + %mul2 = fmul contract float %x, 11.0 + %add1 = fadd contract float %mul1, %mul2 + ret float %add1 +}