42 "disable-ppc-vsx-fma-mutation",
46#define DEBUG_TYPE "ppc-vsx-fma-mutate"
61 const PPCInstrInfo *TII;
64 bool processBlock(MachineBasicBlock &
MBB) {
68 const TargetRegisterInfo *
TRI = &TII->getRegisterInfo();
71 MachineInstr &
MI = *
I;
102 SlotIndex FMAIdx = LIS->getInstructionIndex(
MI);
104 VNInfo *AddendValNo =
105 LIS->getInterval(
MI.getOperand(1).getReg()).Query(FMAIdx).valueIn();
111 MachineInstr *AddendMI = LIS->getInstructionFromIndex(AddendValNo->
def);
115 if (!AddendMI || AddendMI->
getParent() !=
MI.getParent())
126 MRI.getRegClass(AddendSrcReg))
132 ->contains(AddendSrcReg))
154 bool OtherUsers =
false, KillsAddendSrc =
false;
161 if (J->modifiesRegister(AddendSrcReg,
TRI) ||
162 J->killsRegister(AddendSrcReg,
TRI)) {
163 KillsAddendSrc =
true;
168 if (OtherUsers || KillsAddendSrc)
179 Register OldFMAReg =
MI.getOperand(0).getReg();
182 unsigned KilledProdOp = 0, OtherProdOp = 0;
185 if (LIS->getInterval(Reg2).Query(FMAIdx).isKill()
186 && Reg2 != OldFMAReg) {
189 }
else if (LIS->getInterval(Reg3).Query(FMAIdx).isKill()
190 && Reg3 != OldFMAReg) {
206 !LIS->getInterval(AddendSrcReg).liveAt(FMAIdx))
211 Register KilledProdReg =
MI.getOperand(KilledProdOp).getReg();
212 Register OtherProdReg =
MI.getOperand(OtherProdOp).getReg();
215 unsigned KilledProdSubReg =
MI.getOperand(KilledProdOp).getSubReg();
216 unsigned OtherProdSubReg =
MI.getOperand(OtherProdOp).getSubReg();
219 bool KilledProdRegKill =
MI.getOperand(KilledProdOp).isKill();
220 bool OtherProdRegKill =
MI.getOperand(OtherProdOp).isKill();
223 bool KilledProdRegUndef =
MI.getOperand(KilledProdOp).isUndef();
224 bool OtherProdRegUndef =
MI.getOperand(OtherProdOp).isUndef();
230 if (!
MRI.constrainRegClass(KilledProdReg,
231 MRI.getRegClass(OldFMAReg)))
235 "Addend copy not tied to old FMA output!");
239 MI.getOperand(0).setReg(KilledProdReg);
240 MI.getOperand(1).setReg(KilledProdReg);
241 MI.getOperand(3).setReg(AddendSrcReg);
243 MI.getOperand(0).setSubReg(KilledProdSubReg);
244 MI.getOperand(1).setSubReg(KilledProdSubReg);
247 MI.getOperand(1).setIsKill(KilledProdRegKill);
248 MI.getOperand(3).setIsKill(AddRegKill);
250 MI.getOperand(1).setIsUndef(KilledProdRegUndef);
251 MI.getOperand(3).setIsUndef(AddRegUndef);
253 MI.setDesc(TII->get(AltOpc));
258 MI.getOperand(2).setReg(AddendSrcReg);
260 MI.getOperand(2).setIsKill(AddRegKill);
261 MI.getOperand(2).setIsUndef(AddRegUndef);
263 MI.getOperand(2).setReg(OtherProdReg);
264 MI.getOperand(2).setSubReg(OtherProdSubReg);
265 MI.getOperand(2).setIsKill(OtherProdRegKill);
266 MI.getOperand(2).setIsUndef(OtherProdRegUndef);
274 LiveInterval &FMAInt = LIS->getInterval(OldFMAReg);
276 for (
auto UI =
MRI.reg_nodbg_begin(OldFMAReg), UE =
MRI.reg_nodbg_end();
278 MachineOperand &UseMO = *UI;
283 if (
UseMI == AddendMI)
290 LIS->removeInterval(KilledProdReg);
291 LiveInterval &NewFMAInt =
292 LIS->createAndComputeVirtRegInterval(KilledProdReg);
301 for (MCRegUnit Unit :
TRI->regunits(AddendSrcReg.
asMCReg())) {
302 LiveRange &AddendSrcRange = LIS->getRegUnit(Unit);
314 LIS->RemoveMachineInstrFromMaps(*AddendMI);
324 bool runOnMachineFunction(MachineFunction &MF)
override {
330 const PPCSubtarget &STI = MF.
getSubtarget<PPCSubtarget>();
334 LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
350 void getAnalysisUsage(AnalysisUsage &AU)
const override {
357 AU.
addPreserved<MachineBlockFrequencyInfoWrapperPass>();
364 "PowerPC VSX FMA Mutation",
false,
false)
373char PPCVSXFMAMutate::
ID = 0;
375 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.