diff options
Diffstat (limited to 'lib/Target/PowerPC/PPCVSXFMAMutate.cpp')
-rw-r--r-- | lib/Target/PowerPC/PPCVSXFMAMutate.cpp | 68 |
1 files changed, 45 insertions, 23 deletions
diff --git a/lib/Target/PowerPC/PPCVSXFMAMutate.cpp b/lib/Target/PowerPC/PPCVSXFMAMutate.cpp index 6b19a2f7118b2..7c22cb22bfa5f 100644 --- a/lib/Target/PowerPC/PPCVSXFMAMutate.cpp +++ b/lib/Target/PowerPC/PPCVSXFMAMutate.cpp @@ -38,8 +38,14 @@ using namespace llvm; -static cl::opt<bool> DisableVSXFMAMutate("disable-ppc-vsx-fma-mutation", -cl::desc("Disable VSX FMA instruction mutation"), cl::Hidden); +// Temporarily disable FMA mutation by default, since it doesn't handle +// cross-basic-block intervals well. +// See: http://lists.llvm.org/pipermail/llvm-dev/2016-February/095669.html +// http://reviews.llvm.org/D17087 +static cl::opt<bool> DisableVSXFMAMutate( + "disable-ppc-vsx-fma-mutation", + cl::desc("Disable VSX FMA instruction mutation"), cl::init(true), + cl::Hidden); #define DEBUG_TYPE "ppc-vsx-fma-mutate" @@ -99,7 +105,7 @@ protected: // %RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9 // and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9 - SlotIndex FMAIdx = LIS->getInstructionIndex(MI); + SlotIndex FMAIdx = LIS->getInstructionIndex(*MI); VNInfo *AddendValNo = LIS->getInterval(MI->getOperand(1).getReg()).Query(FMAIdx).valueIn(); @@ -168,21 +174,32 @@ protected: if (OtherUsers || KillsAddendSrc) continue; - // Find one of the product operands that is killed by this instruction. + // The transformation doesn't work well with things like: + // %vreg5 = A-form-op %vreg5, %vreg11, %vreg5; + // unless vreg11 is also a kill, so skip when it is not, + // and check operand 3 to see it is also a kill to handle the case: + // %vreg5 = A-form-op %vreg5, %vreg5, %vreg11; + // where vreg5 and vreg11 are both kills. This case would be skipped + // otherwise. + unsigned OldFMAReg = MI->getOperand(0).getReg(); + + // Find one of the product operands that is killed by this instruction. unsigned KilledProdOp = 0, OtherProdOp = 0; - if (LIS->getInterval(MI->getOperand(2).getReg()) - .Query(FMAIdx).isKill()) { + unsigned Reg2 = MI->getOperand(2).getReg(); + unsigned Reg3 = MI->getOperand(3).getReg(); + if (LIS->getInterval(Reg2).Query(FMAIdx).isKill() + && Reg2 != OldFMAReg) { KilledProdOp = 2; OtherProdOp = 3; - } else if (LIS->getInterval(MI->getOperand(3).getReg()) - .Query(FMAIdx).isKill()) { + } else if (LIS->getInterval(Reg3).Query(FMAIdx).isKill() + && Reg3 != OldFMAReg) { KilledProdOp = 3; OtherProdOp = 2; } - // If there are no killed product operands, then this transformation is - // likely not profitable. + // If there are no usable killed product operands, then this + // transformation is likely not profitable. if (!KilledProdOp) continue; @@ -212,14 +229,6 @@ protected: bool KilledProdRegUndef = MI->getOperand(KilledProdOp).isUndef(); bool OtherProdRegUndef = MI->getOperand(OtherProdOp).isUndef(); - unsigned OldFMAReg = MI->getOperand(0).getReg(); - - // The transformation doesn't work well with things like: - // %vreg5 = A-form-op %vreg5, %vreg11, %vreg5; - // so leave such things alone. - if (OldFMAReg == KilledProdReg) - continue; - // If there isn't a class that fits, we can't perform the transform. // This is needed for correctness with a mixture of VSX and Altivec // instructions to make sure that a low VSX register is not assigned to @@ -236,23 +245,33 @@ protected: MI->getOperand(0).setReg(KilledProdReg); MI->getOperand(1).setReg(KilledProdReg); MI->getOperand(3).setReg(AddendSrcReg); - MI->getOperand(2).setReg(OtherProdReg); MI->getOperand(0).setSubReg(KilledProdSubReg); MI->getOperand(1).setSubReg(KilledProdSubReg); MI->getOperand(3).setSubReg(AddSubReg); - MI->getOperand(2).setSubReg(OtherProdSubReg); MI->getOperand(1).setIsKill(KilledProdRegKill); MI->getOperand(3).setIsKill(AddRegKill); - MI->getOperand(2).setIsKill(OtherProdRegKill); MI->getOperand(1).setIsUndef(KilledProdRegUndef); MI->getOperand(3).setIsUndef(AddRegUndef); - MI->getOperand(2).setIsUndef(OtherProdRegUndef); MI->setDesc(TII->get(AltOpc)); + // If the addend is also a multiplicand, replace it with the addend + // source in both places. + if (OtherProdReg == AddendMI->getOperand(0).getReg()) { + MI->getOperand(2).setReg(AddendSrcReg); + MI->getOperand(2).setSubReg(AddSubReg); + MI->getOperand(2).setIsKill(AddRegKill); + MI->getOperand(2).setIsUndef(AddRegUndef); + } else { + MI->getOperand(2).setReg(OtherProdReg); + MI->getOperand(2).setSubReg(OtherProdSubReg); + MI->getOperand(2).setIsKill(OtherProdRegKill); + MI->getOperand(2).setIsUndef(OtherProdRegUndef); + } + DEBUG(dbgs() << " -> " << *MI); // The killed product operand was killed here, so we can reuse it now @@ -312,7 +331,7 @@ protected: // Remove the (now unused) copy. DEBUG(dbgs() << " removing: " << *AddendMI << '\n'); - LIS->RemoveMachineInstrFromMaps(AddendMI); + LIS->RemoveMachineInstrFromMaps(*AddendMI); AddendMI->eraseFromParent(); Changed = true; @@ -323,6 +342,9 @@ protected: public: bool runOnMachineFunction(MachineFunction &MF) override { + if (skipFunction(*MF.getFunction())) + return false; + // If we don't have VSX then go ahead and return without doing // anything. const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>(); |