/// reMaterializeFor - Attempt to rematerialize li_->reg before MI instead of /// reloading it. bool InlineSpiller::reMaterializeFor(MachineBasicBlock::iterator MI) { SlotIndex UseIdx = lis_.getInstructionIndex(MI).getUseIndex(); VNInfo *OrigVNI = li_->getVNInfoAt(UseIdx); if (!OrigVNI) { DEBUG(dbgs() << "\tadding <undef> flags: "); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); if (MO.isReg() && MO.isUse() && MO.getReg() == li_->reg) MO.setIsUndef(); } DEBUG(dbgs() << UseIdx << '\t' << *MI); return true; } if (!reMattable_.count(OrigVNI)) { DEBUG(dbgs() << "\tusing non-remat valno " << OrigVNI->id << ": " << UseIdx << '\t' << *MI); return false; } MachineInstr *OrigMI = lis_.getInstructionFromIndex(OrigVNI->def); if (!allUsesAvailableAt(OrigMI, OrigVNI->def, UseIdx)) { usedValues_.insert(OrigVNI); DEBUG(dbgs() << "\tcannot remat for " << UseIdx << '\t' << *MI); return false; } // If the instruction also writes li_->reg, it had better not require the same // register for uses and defs. bool Reads, Writes; SmallVector<unsigned, 8> Ops; tie(Reads, Writes) = MI->readsWritesVirtualRegister(li_->reg, &Ops); if (Writes) { for (unsigned i = 0, e = Ops.size(); i != e; ++i) { MachineOperand &MO = MI->getOperand(Ops[i]); if (MO.isUse() ? MI->isRegTiedToDefOperand(Ops[i]) : MO.getSubReg()) { usedValues_.insert(OrigVNI); DEBUG(dbgs() << "\tcannot remat tied reg: " << UseIdx << '\t' << *MI); return false; } } } // Alocate a new register for the remat. unsigned NewVReg = mri_.createVirtualRegister(rc_); vrm_.grow(); LiveInterval &NewLI = lis_.getOrCreateInterval(NewVReg); NewLI.markNotSpillable(); newIntervals_->push_back(&NewLI); // Finally we can rematerialize OrigMI before MI. MachineBasicBlock &MBB = *MI->getParent(); tii_.reMaterialize(MBB, MI, NewLI.reg, 0, OrigMI, tri_); MachineBasicBlock::iterator RematMI = MI; SlotIndex DefIdx = lis_.InsertMachineInstrInMaps(--RematMI).getDefIndex(); DEBUG(dbgs() << "\tremat: " << DefIdx << '\t' << *RematMI); // Replace operands for (unsigned i = 0, e = Ops.size(); i != e; ++i) { MachineOperand &MO = MI->getOperand(Ops[i]); if (MO.isReg() && MO.isUse() && MO.getReg() == li_->reg) { MO.setReg(NewVReg); MO.setIsKill(); } } DEBUG(dbgs() << "\t " << UseIdx << '\t' << *MI); VNInfo *DefVNI = NewLI.getNextValue(DefIdx, 0, true, lis_.getVNInfoAllocator()); NewLI.addRange(LiveRange(DefIdx, UseIdx.getDefIndex(), DefVNI)); DEBUG(dbgs() << "\tinterval: " << NewLI << '\n'); return true; }