10b57cec5SDimitry Andric //===--------------- PPCVSXFMAMutate.cpp - VSX FMA Mutation ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This pass mutates the form of VSX FMA instructions to avoid unnecessary
100b57cec5SDimitry Andric // copies.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "MCTargetDesc/PPCPredicates.h"
150b57cec5SDimitry Andric #include "PPC.h"
160b57cec5SDimitry Andric #include "PPCInstrBuilder.h"
170b57cec5SDimitry Andric #include "PPCInstrInfo.h"
180b57cec5SDimitry Andric #include "PPCMachineFunctionInfo.h"
190b57cec5SDimitry Andric #include "PPCTargetMachine.h"
200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
210b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/SlotIndexes.h"
32480093f4SDimitry Andric #include "llvm/InitializePasses.h"
330b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
34349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
350b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
360b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
370b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
380b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric using namespace llvm;
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric // Temporarily disable FMA mutation by default, since it doesn't handle
430b57cec5SDimitry Andric // cross-basic-block intervals well.
440b57cec5SDimitry Andric // See: http://lists.llvm.org/pipermail/llvm-dev/2016-February/095669.html
450b57cec5SDimitry Andric // http://reviews.llvm.org/D17087
460b57cec5SDimitry Andric static cl::opt<bool> DisableVSXFMAMutate(
470b57cec5SDimitry Andric "disable-ppc-vsx-fma-mutation",
480b57cec5SDimitry Andric cl::desc("Disable VSX FMA instruction mutation"), cl::init(true),
490b57cec5SDimitry Andric cl::Hidden);
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric #define DEBUG_TYPE "ppc-vsx-fma-mutate"
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric namespace llvm { namespace PPC {
540b57cec5SDimitry Andric int getAltVSXFMAOpcode(uint16_t Opcode);
550b57cec5SDimitry Andric } }
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric namespace {
580b57cec5SDimitry Andric // PPCVSXFMAMutate pass - For copies between VSX registers and non-VSX registers
590b57cec5SDimitry Andric // (Altivec and scalar floating-point registers), we need to transform the
600b57cec5SDimitry Andric // copies into subregister copies with other restrictions.
610b57cec5SDimitry Andric struct PPCVSXFMAMutate : public MachineFunctionPass {
620b57cec5SDimitry Andric static char ID;
PPCVSXFMAMutate__anon78ef7b5d0111::PPCVSXFMAMutate630b57cec5SDimitry Andric PPCVSXFMAMutate() : MachineFunctionPass(ID) {
640b57cec5SDimitry Andric initializePPCVSXFMAMutatePass(*PassRegistry::getPassRegistry());
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric LiveIntervals *LIS;
680b57cec5SDimitry Andric const PPCInstrInfo *TII;
690b57cec5SDimitry Andric
700b57cec5SDimitry Andric protected:
processBlock__anon78ef7b5d0111::PPCVSXFMAMutate710b57cec5SDimitry Andric bool processBlock(MachineBasicBlock &MBB) {
720b57cec5SDimitry Andric bool Changed = false;
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
750b57cec5SDimitry Andric const TargetRegisterInfo *TRI = &TII->getRegisterInfo();
760b57cec5SDimitry Andric for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end();
770b57cec5SDimitry Andric I != IE; ++I) {
780b57cec5SDimitry Andric MachineInstr &MI = *I;
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric // The default (A-type) VSX FMA form kills the addend (it is taken from
810b57cec5SDimitry Andric // the target register, which is then updated to reflect the result of
820b57cec5SDimitry Andric // the FMA). If the instruction, however, kills one of the registers
830b57cec5SDimitry Andric // used for the product, then we can use the M-form instruction (which
840b57cec5SDimitry Andric // will take that value from the to-be-defined register).
850b57cec5SDimitry Andric
860b57cec5SDimitry Andric int AltOpc = PPC::getAltVSXFMAOpcode(MI.getOpcode());
870b57cec5SDimitry Andric if (AltOpc == -1)
880b57cec5SDimitry Andric continue;
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric // This pass is run after register coalescing, and so we're looking for
910b57cec5SDimitry Andric // a situation like this:
920b57cec5SDimitry Andric // ...
930b57cec5SDimitry Andric // %5 = COPY %9; VSLRC:%5,%9
940b57cec5SDimitry Andric // %5<def,tied1> = XSMADDADP %5<tied0>, %17, %16,
950b57cec5SDimitry Andric // implicit %rm; VSLRC:%5,%17,%16
960b57cec5SDimitry Andric // ...
970b57cec5SDimitry Andric // %9<def,tied1> = XSMADDADP %9<tied0>, %17, %19,
980b57cec5SDimitry Andric // implicit %rm; VSLRC:%9,%17,%19
990b57cec5SDimitry Andric // ...
1000b57cec5SDimitry Andric // Where we can eliminate the copy by changing from the A-type to the
1010b57cec5SDimitry Andric // M-type instruction. Specifically, for this example, this means:
1020b57cec5SDimitry Andric // %5<def,tied1> = XSMADDADP %5<tied0>, %17, %16,
1030b57cec5SDimitry Andric // implicit %rm; VSLRC:%5,%17,%16
1040b57cec5SDimitry Andric // is replaced by:
1050b57cec5SDimitry Andric // %16<def,tied1> = XSMADDMDP %16<tied0>, %18, %9,
1060b57cec5SDimitry Andric // implicit %rm; VSLRC:%16,%18,%9
1070b57cec5SDimitry Andric // and we remove: %5 = COPY %9; VSLRC:%5,%9
1080b57cec5SDimitry Andric
1090b57cec5SDimitry Andric SlotIndex FMAIdx = LIS->getInstructionIndex(MI);
1100b57cec5SDimitry Andric
1110b57cec5SDimitry Andric VNInfo *AddendValNo =
1120b57cec5SDimitry Andric LIS->getInterval(MI.getOperand(1).getReg()).Query(FMAIdx).valueIn();
1130b57cec5SDimitry Andric
1140b57cec5SDimitry Andric // This can be null if the register is undef.
1150b57cec5SDimitry Andric if (!AddendValNo)
1160b57cec5SDimitry Andric continue;
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric MachineInstr *AddendMI = LIS->getInstructionFromIndex(AddendValNo->def);
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric // The addend and this instruction must be in the same block.
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric if (!AddendMI || AddendMI->getParent() != MI.getParent())
1230b57cec5SDimitry Andric continue;
1240b57cec5SDimitry Andric
1250b57cec5SDimitry Andric // The addend must be a full copy within the same register class.
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andric if (!AddendMI->isFullCopy())
1280b57cec5SDimitry Andric continue;
1290b57cec5SDimitry Andric
1308bcb0991SDimitry Andric Register AddendSrcReg = AddendMI->getOperand(1).getReg();
131bdd1243dSDimitry Andric if (AddendSrcReg.isVirtual()) {
1320b57cec5SDimitry Andric if (MRI.getRegClass(AddendMI->getOperand(0).getReg()) !=
1330b57cec5SDimitry Andric MRI.getRegClass(AddendSrcReg))
1340b57cec5SDimitry Andric continue;
1350b57cec5SDimitry Andric } else {
1360b57cec5SDimitry Andric // If AddendSrcReg is a physical register, make sure the destination
1370b57cec5SDimitry Andric // register class contains it.
1380b57cec5SDimitry Andric if (!MRI.getRegClass(AddendMI->getOperand(0).getReg())
1390b57cec5SDimitry Andric ->contains(AddendSrcReg))
1400b57cec5SDimitry Andric continue;
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric // In theory, there could be other uses of the addend copy before this
1440b57cec5SDimitry Andric // fma. We could deal with this, but that would require additional
1450b57cec5SDimitry Andric // logic below and I suspect it will not occur in any relevant
1460b57cec5SDimitry Andric // situations. Additionally, check whether the copy source is killed
1470b57cec5SDimitry Andric // prior to the fma. In order to replace the addend here with the
1480b57cec5SDimitry Andric // source of the copy, it must still be live here. We can't use
1490b57cec5SDimitry Andric // interval testing for a physical register, so as long as we're
1500b57cec5SDimitry Andric // walking the MIs we may as well test liveness here.
1510b57cec5SDimitry Andric //
1520b57cec5SDimitry Andric // FIXME: There is a case that occurs in practice, like this:
1530b57cec5SDimitry Andric // %9 = COPY %f1; VSSRC:%9
1540b57cec5SDimitry Andric // ...
1550b57cec5SDimitry Andric // %6 = COPY %9; VSSRC:%6,%9
1560b57cec5SDimitry Andric // %7 = COPY %9; VSSRC:%7,%9
1570b57cec5SDimitry Andric // %9<def,tied1> = XSMADDASP %9<tied0>, %1, %4; VSSRC:
1580b57cec5SDimitry Andric // %6<def,tied1> = XSMADDASP %6<tied0>, %1, %2; VSSRC:
1590b57cec5SDimitry Andric // %7<def,tied1> = XSMADDASP %7<tied0>, %1, %3; VSSRC:
1600b57cec5SDimitry Andric // which prevents an otherwise-profitable transformation.
1610b57cec5SDimitry Andric bool OtherUsers = false, KillsAddendSrc = false;
1620b57cec5SDimitry Andric for (auto J = std::prev(I), JE = MachineBasicBlock::iterator(AddendMI);
1630b57cec5SDimitry Andric J != JE; --J) {
1640b57cec5SDimitry Andric if (J->readsVirtualRegister(AddendMI->getOperand(0).getReg())) {
1650b57cec5SDimitry Andric OtherUsers = true;
1660b57cec5SDimitry Andric break;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric if (J->modifiesRegister(AddendSrcReg, TRI) ||
1690b57cec5SDimitry Andric J->killsRegister(AddendSrcReg, TRI)) {
1700b57cec5SDimitry Andric KillsAddendSrc = true;
1710b57cec5SDimitry Andric break;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric if (OtherUsers || KillsAddendSrc)
1760b57cec5SDimitry Andric continue;
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric // The transformation doesn't work well with things like:
1800b57cec5SDimitry Andric // %5 = A-form-op %5, %11, %5;
1810b57cec5SDimitry Andric // unless %11 is also a kill, so skip when it is not,
1820b57cec5SDimitry Andric // and check operand 3 to see it is also a kill to handle the case:
1830b57cec5SDimitry Andric // %5 = A-form-op %5, %5, %11;
1840b57cec5SDimitry Andric // where %5 and %11 are both kills. This case would be skipped
1850b57cec5SDimitry Andric // otherwise.
1868bcb0991SDimitry Andric Register OldFMAReg = MI.getOperand(0).getReg();
1870b57cec5SDimitry Andric
1880b57cec5SDimitry Andric // Find one of the product operands that is killed by this instruction.
1890b57cec5SDimitry Andric unsigned KilledProdOp = 0, OtherProdOp = 0;
1908bcb0991SDimitry Andric Register Reg2 = MI.getOperand(2).getReg();
1918bcb0991SDimitry Andric Register Reg3 = MI.getOperand(3).getReg();
1920b57cec5SDimitry Andric if (LIS->getInterval(Reg2).Query(FMAIdx).isKill()
1930b57cec5SDimitry Andric && Reg2 != OldFMAReg) {
1940b57cec5SDimitry Andric KilledProdOp = 2;
1950b57cec5SDimitry Andric OtherProdOp = 3;
1960b57cec5SDimitry Andric } else if (LIS->getInterval(Reg3).Query(FMAIdx).isKill()
1970b57cec5SDimitry Andric && Reg3 != OldFMAReg) {
1980b57cec5SDimitry Andric KilledProdOp = 3;
1990b57cec5SDimitry Andric OtherProdOp = 2;
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric // If there are no usable killed product operands, then this
2030b57cec5SDimitry Andric // transformation is likely not profitable.
2040b57cec5SDimitry Andric if (!KilledProdOp)
2050b57cec5SDimitry Andric continue;
2060b57cec5SDimitry Andric
2070b57cec5SDimitry Andric // If the addend copy is used only by this MI, then the addend source
2080b57cec5SDimitry Andric // register is likely not live here. This could be fixed (based on the
2090b57cec5SDimitry Andric // legality checks above, the live range for the addend source register
2100b57cec5SDimitry Andric // could be extended), but it seems likely that such a trivial copy can
2110b57cec5SDimitry Andric // be coalesced away later, and thus is not worth the effort.
212bdd1243dSDimitry Andric if (AddendSrcReg.isVirtual() &&
2130b57cec5SDimitry Andric !LIS->getInterval(AddendSrcReg).liveAt(FMAIdx))
2140b57cec5SDimitry Andric continue;
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric // Transform: (O2 * O3) + O1 -> (O2 * O1) + O3.
2170b57cec5SDimitry Andric
2188bcb0991SDimitry Andric Register KilledProdReg = MI.getOperand(KilledProdOp).getReg();
2198bcb0991SDimitry Andric Register OtherProdReg = MI.getOperand(OtherProdOp).getReg();
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric unsigned AddSubReg = AddendMI->getOperand(1).getSubReg();
2220b57cec5SDimitry Andric unsigned KilledProdSubReg = MI.getOperand(KilledProdOp).getSubReg();
2230b57cec5SDimitry Andric unsigned OtherProdSubReg = MI.getOperand(OtherProdOp).getSubReg();
2240b57cec5SDimitry Andric
2250b57cec5SDimitry Andric bool AddRegKill = AddendMI->getOperand(1).isKill();
2260b57cec5SDimitry Andric bool KilledProdRegKill = MI.getOperand(KilledProdOp).isKill();
2270b57cec5SDimitry Andric bool OtherProdRegKill = MI.getOperand(OtherProdOp).isKill();
2280b57cec5SDimitry Andric
2290b57cec5SDimitry Andric bool AddRegUndef = AddendMI->getOperand(1).isUndef();
2300b57cec5SDimitry Andric bool KilledProdRegUndef = MI.getOperand(KilledProdOp).isUndef();
2310b57cec5SDimitry Andric bool OtherProdRegUndef = MI.getOperand(OtherProdOp).isUndef();
2320b57cec5SDimitry Andric
2330b57cec5SDimitry Andric // If there isn't a class that fits, we can't perform the transform.
2340b57cec5SDimitry Andric // This is needed for correctness with a mixture of VSX and Altivec
2350b57cec5SDimitry Andric // instructions to make sure that a low VSX register is not assigned to
2360b57cec5SDimitry Andric // the Altivec instruction.
2370b57cec5SDimitry Andric if (!MRI.constrainRegClass(KilledProdReg,
2380b57cec5SDimitry Andric MRI.getRegClass(OldFMAReg)))
2390b57cec5SDimitry Andric continue;
2400b57cec5SDimitry Andric
2410b57cec5SDimitry Andric assert(OldFMAReg == AddendMI->getOperand(0).getReg() &&
2420b57cec5SDimitry Andric "Addend copy not tied to old FMA output!");
2430b57cec5SDimitry Andric
2440b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "VSX FMA Mutation:\n " << MI);
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric MI.getOperand(0).setReg(KilledProdReg);
2470b57cec5SDimitry Andric MI.getOperand(1).setReg(KilledProdReg);
2480b57cec5SDimitry Andric MI.getOperand(3).setReg(AddendSrcReg);
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andric MI.getOperand(0).setSubReg(KilledProdSubReg);
2510b57cec5SDimitry Andric MI.getOperand(1).setSubReg(KilledProdSubReg);
2520b57cec5SDimitry Andric MI.getOperand(3).setSubReg(AddSubReg);
2530b57cec5SDimitry Andric
2540b57cec5SDimitry Andric MI.getOperand(1).setIsKill(KilledProdRegKill);
2550b57cec5SDimitry Andric MI.getOperand(3).setIsKill(AddRegKill);
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andric MI.getOperand(1).setIsUndef(KilledProdRegUndef);
2580b57cec5SDimitry Andric MI.getOperand(3).setIsUndef(AddRegUndef);
2590b57cec5SDimitry Andric
2600b57cec5SDimitry Andric MI.setDesc(TII->get(AltOpc));
2610b57cec5SDimitry Andric
2620b57cec5SDimitry Andric // If the addend is also a multiplicand, replace it with the addend
2630b57cec5SDimitry Andric // source in both places.
2640b57cec5SDimitry Andric if (OtherProdReg == AddendMI->getOperand(0).getReg()) {
2650b57cec5SDimitry Andric MI.getOperand(2).setReg(AddendSrcReg);
2660b57cec5SDimitry Andric MI.getOperand(2).setSubReg(AddSubReg);
2670b57cec5SDimitry Andric MI.getOperand(2).setIsKill(AddRegKill);
2680b57cec5SDimitry Andric MI.getOperand(2).setIsUndef(AddRegUndef);
2690b57cec5SDimitry Andric } else {
2700b57cec5SDimitry Andric MI.getOperand(2).setReg(OtherProdReg);
2710b57cec5SDimitry Andric MI.getOperand(2).setSubReg(OtherProdSubReg);
2720b57cec5SDimitry Andric MI.getOperand(2).setIsKill(OtherProdRegKill);
2730b57cec5SDimitry Andric MI.getOperand(2).setIsUndef(OtherProdRegUndef);
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric
2760b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " -> " << MI);
2770b57cec5SDimitry Andric
2780b57cec5SDimitry Andric // The killed product operand was killed here, so we can reuse it now
2790b57cec5SDimitry Andric // for the result of the fma.
2800b57cec5SDimitry Andric
2810b57cec5SDimitry Andric LiveInterval &FMAInt = LIS->getInterval(OldFMAReg);
2820b57cec5SDimitry Andric VNInfo *FMAValNo = FMAInt.getVNInfoAt(FMAIdx.getRegSlot());
2830b57cec5SDimitry Andric for (auto UI = MRI.reg_nodbg_begin(OldFMAReg), UE = MRI.reg_nodbg_end();
2840b57cec5SDimitry Andric UI != UE;) {
2850b57cec5SDimitry Andric MachineOperand &UseMO = *UI;
2860b57cec5SDimitry Andric MachineInstr *UseMI = UseMO.getParent();
2870b57cec5SDimitry Andric ++UI;
2880b57cec5SDimitry Andric
2890b57cec5SDimitry Andric // Don't replace the result register of the copy we're about to erase.
2900b57cec5SDimitry Andric if (UseMI == AddendMI)
2910b57cec5SDimitry Andric continue;
2920b57cec5SDimitry Andric
2930b57cec5SDimitry Andric UseMO.substVirtReg(KilledProdReg, KilledProdSubReg, *TRI);
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
2960b57cec5SDimitry Andric // Extend the live intervals of the killed product operand to hold the
2970b57cec5SDimitry Andric // fma result.
2980b57cec5SDimitry Andric
2990b57cec5SDimitry Andric LiveInterval &NewFMAInt = LIS->getInterval(KilledProdReg);
30004eeddc0SDimitry Andric for (auto &AI : FMAInt) {
3010b57cec5SDimitry Andric // Don't add the segment that corresponds to the original copy.
30204eeddc0SDimitry Andric if (AI.valno == AddendValNo)
3030b57cec5SDimitry Andric continue;
3040b57cec5SDimitry Andric
3050b57cec5SDimitry Andric VNInfo *NewFMAValNo =
30604eeddc0SDimitry Andric NewFMAInt.getNextValue(AI.start, LIS->getVNInfoAllocator());
3070b57cec5SDimitry Andric
30804eeddc0SDimitry Andric NewFMAInt.addSegment(
30904eeddc0SDimitry Andric LiveInterval::Segment(AI.start, AI.end, NewFMAValNo));
3100b57cec5SDimitry Andric }
3110b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " extended: " << NewFMAInt << '\n');
3120b57cec5SDimitry Andric
3130b57cec5SDimitry Andric // Extend the live interval of the addend source (it might end at the
3140b57cec5SDimitry Andric // copy to be removed, or somewhere in between there and here). This
3150b57cec5SDimitry Andric // is necessary only if it is a physical register.
316e8d8bef9SDimitry Andric if (!AddendSrcReg.isVirtual())
31706c3fb27SDimitry Andric for (MCRegUnit Unit : TRI->regunits(AddendSrcReg.asMCReg())) {
3180b57cec5SDimitry Andric LiveRange &AddendSrcRange = LIS->getRegUnit(Unit);
3190b57cec5SDimitry Andric AddendSrcRange.extendInBlock(LIS->getMBBStartIdx(&MBB),
3200b57cec5SDimitry Andric FMAIdx.getRegSlot());
3210b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " extended: " << AddendSrcRange << '\n');
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric
3240b57cec5SDimitry Andric FMAInt.removeValNo(FMAValNo);
3250b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " trimmed: " << FMAInt << '\n');
3260b57cec5SDimitry Andric
3270b57cec5SDimitry Andric // Remove the (now unused) copy.
3280b57cec5SDimitry Andric
3290b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " removing: " << *AddendMI << '\n');
3300b57cec5SDimitry Andric LIS->RemoveMachineInstrFromMaps(*AddendMI);
3310b57cec5SDimitry Andric AddendMI->eraseFromParent();
3320b57cec5SDimitry Andric
3330b57cec5SDimitry Andric Changed = true;
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric
3360b57cec5SDimitry Andric return Changed;
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric
3390b57cec5SDimitry Andric public:
runOnMachineFunction__anon78ef7b5d0111::PPCVSXFMAMutate3400b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override {
3410b57cec5SDimitry Andric if (skipFunction(MF.getFunction()))
3420b57cec5SDimitry Andric return false;
3430b57cec5SDimitry Andric
3440b57cec5SDimitry Andric // If we don't have VSX then go ahead and return without doing
3450b57cec5SDimitry Andric // anything.
3460b57cec5SDimitry Andric const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>();
3470b57cec5SDimitry Andric if (!STI.hasVSX())
3480b57cec5SDimitry Andric return false;
3490b57cec5SDimitry Andric
350*0fca6ea1SDimitry Andric LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric TII = STI.getInstrInfo();
3530b57cec5SDimitry Andric
3540b57cec5SDimitry Andric bool Changed = false;
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric if (DisableVSXFMAMutate)
3570b57cec5SDimitry Andric return Changed;
3580b57cec5SDimitry Andric
359349cc55cSDimitry Andric for (MachineBasicBlock &B : llvm::make_early_inc_range(MF))
3600b57cec5SDimitry Andric if (processBlock(B))
3610b57cec5SDimitry Andric Changed = true;
3620b57cec5SDimitry Andric
3630b57cec5SDimitry Andric return Changed;
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric
getAnalysisUsage__anon78ef7b5d0111::PPCVSXFMAMutate3660b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
367*0fca6ea1SDimitry Andric AU.addRequired<LiveIntervalsWrapperPass>();
368*0fca6ea1SDimitry Andric AU.addPreserved<LiveIntervalsWrapperPass>();
369*0fca6ea1SDimitry Andric AU.addRequired<SlotIndexesWrapperPass>();
370*0fca6ea1SDimitry Andric AU.addPreserved<SlotIndexesWrapperPass>();
371*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>();
372*0fca6ea1SDimitry Andric AU.addPreserved<MachineDominatorTreeWrapperPass>();
3730b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric };
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric
3780b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(PPCVSXFMAMutate, DEBUG_TYPE,
3790b57cec5SDimitry Andric "PowerPC VSX FMA Mutation", false, false)
380*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass)
381*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(SlotIndexesWrapperPass)
382*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
3830b57cec5SDimitry Andric INITIALIZE_PASS_END(PPCVSXFMAMutate, DEBUG_TYPE,
3840b57cec5SDimitry Andric "PowerPC VSX FMA Mutation", false, false)
3850b57cec5SDimitry Andric
3860b57cec5SDimitry Andric char &llvm::PPCVSXFMAMutateID = PPCVSXFMAMutate::ID;
3870b57cec5SDimitry Andric
3880b57cec5SDimitry Andric char PPCVSXFMAMutate::ID = 0;
createPPCVSXFMAMutatePass()3890b57cec5SDimitry Andric FunctionPass *llvm::createPPCVSXFMAMutatePass() {
3900b57cec5SDimitry Andric return new PPCVSXFMAMutate();
3910b57cec5SDimitry Andric }
392