/// PropagateForward - Traverse forward and look for the kill of OldReg. If /// it can successfully update all of the uses with NewReg, do so and /// return true. bool StackSlotColoring::PropagateForward(MachineBasicBlock::iterator MII, MachineBasicBlock *MBB, unsigned OldReg, unsigned NewReg) { if (MII == MBB->end()) return false; SmallVector<MachineOperand*, 4> Uses; while (++MII != MBB->end()) { bool FoundKill = false; const TargetInstrDesc &TID = MII->getDesc(); for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { MachineOperand &MO = MII->getOperand(i); if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); if (Reg == 0) continue; if (Reg == OldReg) { if (MO.isDef() || MO.isImplicit()) return false; // Abort the use is actually a sub-register use. We don't have enough // information to figure out if it is really legal. if (MO.getSubReg() || MII->isExtractSubreg()) return false; const TargetRegisterClass *RC = TID.OpInfo[i].getRegClass(TRI); if (RC && !RC->contains(NewReg)) return false; if (MO.isKill()) FoundKill = true; Uses.push_back(&MO); } else if (TRI->regsOverlap(Reg, NewReg) || TRI->regsOverlap(Reg, OldReg)) return false; } if (FoundKill) { for (unsigned i = 0, e = Uses.size(); i != e; ++i) Uses[i]->setReg(NewReg); return true; } } return false; }
/// PropagateBackward - Traverse backward and look for the definition of /// OldReg. If it can successfully update all of the references with NewReg, /// do so and return true. bool StackSlotColoring::PropagateBackward(MachineBasicBlock::iterator MII, MachineBasicBlock *MBB, unsigned OldReg, unsigned NewReg) { if (MII == MBB->begin()) return false; SmallVector<MachineOperand*, 4> Uses; SmallVector<MachineOperand*, 4> Refs; while (--MII != MBB->begin()) { bool FoundDef = false; // Not counting 2address def. Uses.clear(); const TargetInstrDesc &TID = MII->getDesc(); for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { MachineOperand &MO = MII->getOperand(i); if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); if (Reg == 0) continue; if (Reg == OldReg) { if (MO.isImplicit()) return false; // Abort the use is actually a sub-register def. We don't have enough // information to figure out if it is really legal. if (MO.getSubReg() || MII->isExtractSubreg() || MII->isInsertSubreg() || MII->isSubregToReg()) return false; const TargetRegisterClass *RC = TID.OpInfo[i].getRegClass(TRI); if (RC && !RC->contains(NewReg)) return false; if (MO.isUse()) { Uses.push_back(&MO); } else { Refs.push_back(&MO); if (!MII->isRegTiedToUseOperand(i)) FoundDef = true; } } else if (TRI->regsOverlap(Reg, NewReg)) { return false; } else if (TRI->regsOverlap(Reg, OldReg)) { if (!MO.isUse() || !MO.isKill()) return false; } } if (FoundDef) { // Found non-two-address def. Stop here. for (unsigned i = 0, e = Refs.size(); i != e; ++i) Refs[i]->setReg(NewReg); return true; } // Two-address uses must be updated as well. for (unsigned i = 0, e = Uses.size(); i != e; ++i) Refs.push_back(Uses[i]); } return false; }