Index: lib/Target/PowerPC/PPCInstrInfo.cpp =================================================================== --- lib/Target/PowerPC/PPCInstrInfo.cpp +++ lib/Target/PowerPC/PPCInstrInfo.cpp @@ -1622,6 +1622,7 @@ bool Changed = false; MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); + const TargetRegisterInfo *TRI = &TII->getRegisterInfo(); for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end(); I != IE; ++I) { MachineInstr *MI = I; @@ -1687,16 +1688,26 @@ // In theory, there could be other uses of the addend copy before this // fma. We could deal with this, but that would require additional // logic below and I suspect it will not occur in any relevant - // situations. - bool OtherUsers = false; + // situations. Additionally, check for whether the copy source is + // killed prior to the fma. In order to replace the addend here with + // the source of the copy, it must still be live here. We can't use + // interval testing for a physical register, so as long as we're + // walking the MIs we may as well test liveness here. + bool OtherUsers = false, KillsAddendSrc = false; for (auto J = std::prev(I), JE = MachineBasicBlock::iterator(AddendMI); - J != JE; --J) + J != JE; --J) { if (J->readsVirtualRegister(AddendMI->getOperand(0).getReg())) { OtherUsers = true; break; } + if (J->modifiesRegister(AddendSrcReg, TRI) || + J->killsRegister(AddendSrcReg, TRI)) { + KillsAddendSrc = true; + break; + } + } - if (OtherUsers) + if (OtherUsers || KillsAddendSrc) continue; // Find one of the product operands that is killed by this instruction. @@ -1717,11 +1728,6 @@ if (!KilledProdOp) continue; - // In order to replace the addend here with the source of the copy, - // it must still be live here. - if (!LIS->getInterval(AddendMI->getOperand(1).getReg()).liveAt(FMAIdx)) - continue; - // Transform: (O2 * O3) + O1 -> (O2 * O1) + O3. unsigned AddReg = AddendMI->getOperand(1).getReg(); Index: test/CodeGen/PowerPC/fma.ll =================================================================== --- test/CodeGen/PowerPC/fma.ll +++ test/CodeGen/PowerPC/fma.ll @@ -1,4 +1,5 @@ -; RUN: llc < %s -march=ppc32 -fp-contract=fast | FileCheck %s +; RUN: llc < %s -march=ppc32 -fp-contract=fast -mattr=-vsx | FileCheck %s +; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -fp-contract=fast -mattr=+vsx | FileCheck -check-prefix=CHECK-VSX %s declare double @dummy1(double) #0 declare double @dummy2(double, double) #0 @@ -11,6 +12,10 @@ ; CHECK-LABEL: test_FMADD1: ; CHECK: fmadd ; CHECK-NEXT: blr + +; CHECK-VSX-LABEL: test_FMADD1: +; CHECK-VSX: xsmaddmdp +; CHECK-VSX-NEXT: blr } define double @test_FMADD2(double %A, double %B, double %C) { @@ -20,6 +25,10 @@ ; CHECK-LABEL: test_FMADD2: ; CHECK: fmadd ; CHECK-NEXT: blr + +; CHECK-VSX-LABEL: test_FMADD2: +; CHECK-VSX: xsmaddmdp +; CHECK-VSX-NEXT: blr } define double @test_FMSUB1(double %A, double %B, double %C) { @@ -29,6 +38,10 @@ ; CHECK-LABEL: test_FMSUB1: ; CHECK: fmsub ; CHECK-NEXT: blr + +; CHECK-VSX-LABEL: test_FMSUB1: +; CHECK-VSX: xsmsubmdp +; CHECK-VSX-NEXT: blr } define double @test_FMSUB2(double %A, double %B, double %C, double %D) { @@ -40,6 +53,10 @@ ; CHECK-LABEL: test_FMSUB2: ; CHECK: fmadd ; CHECK-NEXT: fmsub + +; CHECK-VSX-LABEL: test_FMSUB2: +; CHECK-VSX: xsmaddadp +; CHECK-VSX-NEXT: xsmsubmdp } define double @test_FNMADD1(double %A, double %B, double %C) { @@ -50,6 +67,10 @@ ; CHECK-LABEL: test_FNMADD1: ; CHECK: fnmadd ; CHECK-NEXT: blr + +; CHECK-VSX-LABEL: test_FNMADD1: +; CHECK-VSX: xsnmaddmdp +; CHECK-VSX-NEXT: blr } define double @test_FNMADD2(double %A, double %B, double %C) { @@ -60,6 +81,10 @@ ; CHECK-LABEL: test_FNMADD2: ; CHECK: fnmadd ; CHECK-NEXT: blr + +; CHECK-VSX-LABEL: test_FNMADD2: +; CHECK-VSX: xsnmaddmdp +; CHECK-VSX-NEXT: blr } define double @test_FNMSUB1(double %A, double %B, double %C) { @@ -69,6 +94,9 @@ ; CHECK-LABEL: test_FNMSUB1: ; CHECK: fnmsub ; CHECK-NEXT: blr + +; CHECK-VSX-LABEL: test_FNMSUB1: +; CHECK-VSX: xsnmsubmdp } define double @test_FNMSUB2(double %A, double %B, double %C) { @@ -79,6 +107,10 @@ ; CHECK-LABEL: test_FNMSUB2: ; CHECK: fnmsub ; CHECK-NEXT: blr + +; CHECK-VSX-LABEL: test_FNMSUB2: +; CHECK-VSX: xsnmsubmdp +; CHECK-VSX-NEXT: blr } define float @test_FNMSUBS(float %A, float %B, float %C) { @@ -89,4 +121,8 @@ ; CHECK-LABEL: test_FNMSUBS: ; CHECK: fnmsubs ; CHECK-NEXT: blr + +; CHECK-VSX-LABEL: test_FNMSUBS: +; CHECK-VSX: fnmsubs +; CHECK-VSX-NEXT: blr }