43 "disable-ppc-vsx-fma-mutation",
47#define DEBUG_TYPE "ppc-vsx-fma-mutate"
62 const PPCInstrInfo *TII;
65 bool processBlock(MachineBasicBlock &
MBB) {
69 const TargetRegisterInfo *
TRI = &TII->getRegisterInfo();
72 MachineInstr &
MI = *
I;
103 SlotIndex FMAIdx = LIS->getInstructionIndex(
MI);
105 VNInfo *AddendValNo =
106 LIS->getInterval(
MI.getOperand(1).getReg()).Query(FMAIdx).valueIn();
112 MachineInstr *AddendMI = LIS->getInstructionFromIndex(AddendValNo->
def);
116 if (!AddendMI || AddendMI->
getParent() !=
MI.getParent())
127 MRI.getRegClass(AddendSrcReg))
133 ->contains(AddendSrcReg))
155 bool OtherUsers =
false, KillsAddendSrc =
false;
162 if (J->modifiesRegister(AddendSrcReg,
TRI) ||
163 J->killsRegister(AddendSrcReg,
TRI)) {
164 KillsAddendSrc =
true;
169 if (OtherUsers || KillsAddendSrc)
180 Register OldFMAReg =
MI.getOperand(0).getReg();
183 unsigned KilledProdOp = 0, OtherProdOp = 0;
186 if (LIS->getInterval(Reg2).Query(FMAIdx).isKill()
187 && Reg2 != OldFMAReg) {
190 }
else if (LIS->getInterval(Reg3).Query(FMAIdx).isKill()
191 && Reg3 != OldFMAReg) {
207 !LIS->getInterval(AddendSrcReg).liveAt(FMAIdx))
212 Register KilledProdReg =
MI.getOperand(KilledProdOp).getReg();
213 Register OtherProdReg =
MI.getOperand(OtherProdOp).getReg();
216 unsigned KilledProdSubReg =
MI.getOperand(KilledProdOp).getSubReg();
217 unsigned OtherProdSubReg =
MI.getOperand(OtherProdOp).getSubReg();
220 bool KilledProdRegKill =
MI.getOperand(KilledProdOp).isKill();
221 bool OtherProdRegKill =
MI.getOperand(OtherProdOp).isKill();
224 bool KilledProdRegUndef =
MI.getOperand(KilledProdOp).isUndef();
225 bool OtherProdRegUndef =
MI.getOperand(OtherProdOp).isUndef();
231 if (!
MRI.constrainRegClass(KilledProdReg,
232 MRI.getRegClass(OldFMAReg)))
236 "Addend copy not tied to old FMA output!");
240 MI.getOperand(0).setReg(KilledProdReg);
241 MI.getOperand(1).setReg(KilledProdReg);
242 MI.getOperand(3).setReg(AddendSrcReg);
244 MI.getOperand(0).setSubReg(KilledProdSubReg);
245 MI.getOperand(1).setSubReg(KilledProdSubReg);
248 MI.getOperand(1).setIsKill(KilledProdRegKill);
249 MI.getOperand(3).setIsKill(AddRegKill);
251 MI.getOperand(1).setIsUndef(KilledProdRegUndef);
252 MI.getOperand(3).setIsUndef(AddRegUndef);
254 MI.setDesc(TII->get(AltOpc));
259 MI.getOperand(2).setReg(AddendSrcReg);
261 MI.getOperand(2).setIsKill(AddRegKill);
262 MI.getOperand(2).setIsUndef(AddRegUndef);
264 MI.getOperand(2).setReg(OtherProdReg);
265 MI.getOperand(2).setSubReg(OtherProdSubReg);
266 MI.getOperand(2).setIsKill(OtherProdRegKill);
267 MI.getOperand(2).setIsUndef(OtherProdRegUndef);
275 LiveInterval &FMAInt = LIS->getInterval(OldFMAReg);
277 for (
auto UI =
MRI.reg_nodbg_begin(OldFMAReg), UE =
MRI.reg_nodbg_end();
279 MachineOperand &UseMO = *UI;
284 if (
UseMI == AddendMI)
291 LIS->removeInterval(KilledProdReg);
292 LiveInterval &NewFMAInt =
293 LIS->createAndComputeVirtRegInterval(KilledProdReg);
302 for (MCRegUnit Unit :
TRI->regunits(AddendSrcReg.
asMCReg())) {
303 LiveRange &AddendSrcRange = LIS->getRegUnit(Unit);
315 LIS->RemoveMachineInstrFromMaps(*AddendMI);
325 bool runOnMachineFunction(MachineFunction &MF)
override {
331 const PPCSubtarget &STI = MF.
getSubtarget<PPCSubtarget>();
335 LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
351 void getAnalysisUsage(AnalysisUsage &AU)
const override {
358 AU.
addPreserved<MachineBlockFrequencyInfoWrapperPass>();
365 "PowerPC VSX FMA Mutation",
false,
false)
374char PPCVSXFMAMutate::
ID = 0;
376 return new PPCVSXFMAMutate();
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
static const MachineInstrBuilder & AddSubReg(const MachineInstrBuilder &MIB, MCRegister Reg, unsigned SubIdx, unsigned State, const TargetRegisterInfo *TRI)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static cl::opt< bool > DisableVSXFMAMutate("disable-ppc-vsx-fma-mutation", cl::desc("Disable VSX FMA instruction mutation"), cl::init(true), cl::Hidden)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
SI Optimize VGPR LiveRange
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
FunctionPass class - This class is used to implement most global optimizations.
LLVM_ABI void removeValNo(VNInfo *ValNo)
removeValNo - Remove all the segments defined by the specified value#.
LLVM_ABI std::pair< VNInfo *, bool > extendInBlock(ArrayRef< SlotIndex > Undefs, SlotIndex StartIdx, SlotIndex Kill)
Attempt to extend a value defined after StartIdx to include Use.
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock * getParent() const
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
unsigned getSubReg() const
LLVM_ABI void substVirtReg(Register Reg, unsigned SubIdx, const TargetRegisterInfo &)
substVirtReg - Substitute the current register with the virtual subregister Reg:SubReg.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
Register getReg() const
getReg - Returns the register number.
const PPCInstrInfo * getInstrInfo() const override
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
SlotIndex def
The index of the defining instruction.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Define some predicates that are used for node matching.
int getAltVSXFMAOpcode(uint16_t Opcode)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createPPCVSXFMAMutatePass()
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.