/// Return true when an instruction has tied register that can't be determined /// by the instruction's descriptor. static bool hasComplexRegisterTies(const MachineInstr &MI) { const MCInstrDesc &MCID = MI.getDesc(); for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) { const auto &Operand = MI.getOperand(I); if (!Operand.isReg() || Operand.isDef()) // Ignore the defined registers as MCID marks only the uses as tied. continue; int ExpectedTiedIdx = MCID.getOperandConstraint(I, MCOI::TIED_TO); int TiedIdx = Operand.isTied() ? int(MI.findTiedOperandIdx(I)) : -1; if (ExpectedTiedIdx != TiedIdx) return true; } return false; }
// Handles special instruction operand like early clobbers and tied ops when // there are additional physreg defines. void RegAllocFast::handleThroughOperands(MachineInstr &MI, SmallVectorImpl<unsigned> &VirtDead) { LLVM_DEBUG(dbgs() << "Scanning for through registers:"); SmallSet<unsigned, 8> ThroughRegs; for (const MachineOperand &MO : MI.operands()) { if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; if (MO.isEarlyClobber() || (MO.isUse() && MO.isTied()) || (MO.getSubReg() && MI.readsVirtualRegister(Reg))) { if (ThroughRegs.insert(Reg).second) LLVM_DEBUG(dbgs() << ' ' << printReg(Reg)); } } // If any physreg defines collide with preallocated through registers, // we must spill and reallocate. LLVM_DEBUG(dbgs() << "\nChecking for physdef collisions.\n"); for (const MachineOperand &MO : MI.operands()) { if (!MO.isReg() || !MO.isDef()) continue; unsigned Reg = MO.getReg(); if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg)) continue; markRegUsedInInstr(Reg); for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) { if (ThroughRegs.count(PhysRegState[*AI])) definePhysReg(MI, *AI, regFree); } } SmallVector<unsigned, 8> PartialDefs; LLVM_DEBUG(dbgs() << "Allocating tied uses.\n"); for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) { MachineOperand &MO = MI.getOperand(I); if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; if (MO.isUse()) { if (!MO.isTied()) continue; LLVM_DEBUG(dbgs() << "Operand " << I << "(" << MO << ") is tied to operand " << MI.findTiedOperandIdx(I) << ".\n"); LiveReg &LR = reloadVirtReg(MI, I, Reg, 0); MCPhysReg PhysReg = LR.PhysReg; setPhysReg(MI, MO, PhysReg); // Note: we don't update the def operand yet. That would cause the normal // def-scan to attempt spilling. } else if (MO.getSubReg() && MI.readsVirtualRegister(Reg)) { LLVM_DEBUG(dbgs() << "Partial redefine: " << MO << '\n'); // Reload the register, but don't assign to the operand just yet. // That would confuse the later phys-def processing pass. LiveReg &LR = reloadVirtReg(MI, I, Reg, 0); PartialDefs.push_back(LR.PhysReg); } } LLVM_DEBUG(dbgs() << "Allocating early clobbers.\n"); for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) { const MachineOperand &MO = MI.getOperand(I); if (!MO.isReg()) continue; unsigned Reg = MO.getReg(); if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; if (!MO.isEarlyClobber()) continue; // Note: defineVirtReg may invalidate MO. MCPhysReg PhysReg = defineVirtReg(MI, I, Reg, 0); if (setPhysReg(MI, MI.getOperand(I), PhysReg)) VirtDead.push_back(Reg); } // Restore UsedInInstr to a state usable for allocating normal virtual uses. UsedInInstr.clear(); for (const MachineOperand &MO : MI.operands()) { if (!MO.isReg() || (MO.isDef() && !MO.isEarlyClobber())) continue; unsigned Reg = MO.getReg(); if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg)) continue; LLVM_DEBUG(dbgs() << "\tSetting " << printReg(Reg, TRI) << " as used in instr\n"); markRegUsedInInstr(Reg); } // Also mark PartialDefs as used to avoid reallocation. for (unsigned PartialDef : PartialDefs) markRegUsedInInstr(PartialDef); }