Index: lib/CodeGen/MachineCopyPropagation.cpp =================================================================== --- lib/CodeGen/MachineCopyPropagation.cpp +++ lib/CodeGen/MachineCopyPropagation.cpp @@ -179,6 +179,8 @@ MachineInstr *MI = &*I; ++I; + const MachineOperand *RegMask = nullptr; + if (MI->isCopy()) { unsigned Def = MI->getOperand(0).getReg(); unsigned Src = MI->getOperand(1).getReg(); @@ -229,6 +231,9 @@ // ... // %xmm2 = copy %xmm9 ClobberRegister(Def); + // Handle any second implicit def operand. + if (MI->getNumOperands() == 3 && MI->getOperand(2).isDef()) + ClobberRegister(MI->getOperand(2).getReg()); // Remember Def is defined by the copy. for (MCSubRegIterator SR(Def, TRI, /*IncludeSelf=*/true); SR.isValid(); @@ -242,77 +247,107 @@ RegList &DestList = SrcMap[Src]; if (std::find(DestList.begin(), DestList.end(), Def) == DestList.end()) DestList.push_back(Def); - - continue; } + else { + // Not a copy. + SmallVector Defs; + for (unsigned MOIdx = 0; MOIdx < MI->getNumOperands() ; ++MOIdx) { + MachineOperand &MO = MI->getOperand(MOIdx); + if (MO.isRegMask()) + RegMask = &MO; + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; - // Not a copy. - SmallVector Defs; - const MachineOperand *RegMask = nullptr; - for (const MachineOperand &MO : MI->operands()) { - if (MO.isRegMask()) - RegMask = &MO; - if (!MO.isReg()) - continue; - unsigned Reg = MO.getReg(); - if (!Reg) - continue; + assert(!TargetRegisterInfo::isVirtualRegister(Reg) && + "MachineCopyPropagation should be run after register " + "allocation!"); - assert(!TargetRegisterInfo::isVirtualRegister(Reg) && - "MachineCopyPropagation should be run after register allocation!"); + if (MO.isDef()) { + Defs.push_back(Reg); + continue; + } - if (MO.isDef()) { - Defs.push_back(Reg); - continue; - } + // If 'Reg' is killed and is defined by a previous copy of a + // register that is also in the right register class, use that + // earlier source register instead. This may make that previous + // copy removable. Skipping subregs and multiple uses for now. + if (!MRI->isReserved(Reg) && + MO.readsReg() && MO.isKill() && !MO.isTied() && + !TII->isGenericOpcode(MI->getOpcode())) { + Reg2MIMap::iterator CI = AvailCopyMap.find(MO.getReg()); + if (CI != AvailCopyMap.end()) { + MachineInstr &PrevCopy = *CI->second; + MachineOperand &PrevCopySrc = PrevCopy.getOperand(1); + const TargetRegisterClass *RC = + TII->getRegClass(MI->getDesc(), MOIdx, TRI, *MBB.getParent()); + if (!MRI->isReserved(PrevCopySrc.getReg()) && + !PrevCopySrc.getSubReg() && + RC != nullptr && RC->contains(PrevCopySrc.getReg())) { + MO.setReg(PrevCopySrc.getReg()); + continue; + } + } + } - // If 'Reg' is defined by a copy, the copy is no longer a candidate - // for elimination. - for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) { - Reg2MIMap::iterator CI = CopyMap.find(*AI); - if (CI != CopyMap.end()) { - DEBUG(dbgs() << "MCP: Copy is used - not dead: "; CI->second->dump()); - MaybeDeadCopies.remove(CI->second); + // If 'Reg' is defined by a copy, the copy is no longer a candidate + // for elimination. + for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) { + Reg2MIMap::iterator CI = CopyMap.find(*AI); + if (CI != CopyMap.end()) { + DEBUG(dbgs() << "MCP: Copy is used - not dead: "; CI->second->dump()); + MaybeDeadCopies.remove(CI->second); + } } + // Treat undef use like defs for copy propagation but not for + // dead copy. We would need to do a liveness check to be sure the copy + // is dead for undef uses. + // The backends are allowed to do whatever they want with undef value + // and we cannot be sure this register will not be rewritten to break + // some false dependencies for the hardware for instance. + if (MO.isUndef()) + Defs.push_back(Reg); } - // Treat undef use like defs for copy propagation but not for - // dead copy. We would need to do a liveness check to be sure the copy - // is dead for undef uses. - // The backends are allowed to do whatever they want with undef value - // and we cannot be sure this register will not be rewritten to break - // some false dependencies for the hardware for instance. - if (MO.isUndef()) - Defs.push_back(Reg); + + // Any previous copy definition or reading the Defs is no longer available. + for (unsigned Reg : Defs) + ClobberRegister(Reg); } - // The instruction has a register mask operand which means that it clobbers - // a large set of registers. Treat clobbered registers the same way as - // defined registers. - if (RegMask) { - // Erase any MaybeDeadCopies whose destination register is clobbered. - for (SmallSetVector::iterator DI = - MaybeDeadCopies.begin(); - DI != MaybeDeadCopies.end();) { - MachineInstr *MaybeDead = *DI; - unsigned Reg = MaybeDead->getOperand(0).getReg(); - assert(!MRI->isReserved(Reg)); - - if (!RegMask->clobbersPhysReg(Reg)) { - ++DI; - continue; - } + // Erase any MaybeDeadCopies whose destination register was clobbered. + for (SmallSetVector::iterator DI = + MaybeDeadCopies.begin(); + DI != MaybeDeadCopies.end();) { + MachineInstr *MaybeDead = *DI; + if (MaybeDead == MI) { + ++DI; + continue; + } + unsigned Reg = MaybeDead->getOperand(0).getReg(); + assert(!MRI->isReserved(Reg)); + if (MI->definesRegister(Reg, TRI)) + DEBUG(dbgs() << "MCP: Removing copy due to def: "; + MaybeDead->dump()); + else if (RegMask && RegMask->clobbersPhysReg(Reg)) DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: "; MaybeDead->dump()); - - // erase() will return the next valid iterator pointing to the next - // element after the erased one. - DI = MaybeDeadCopies.erase(DI); - MaybeDead->eraseFromParent(); - Changed = true; - ++NumDeletes; + else { + ++DI; + continue; } + // erase() will return the next valid iterator pointing to the next + // element after the erased one. + DI = MaybeDeadCopies.erase(DI); + MaybeDead->eraseFromParent(); + Changed = true; + ++NumDeletes; + } + + if (RegMask) { removeClobberedRegsFromMap(AvailCopyMap, *RegMask); removeClobberedRegsFromMap(CopyMap, *RegMask); for (SourceMap::iterator I = SrcMap.begin(), E = SrcMap.end(), Next; @@ -324,10 +359,6 @@ } } } - - // Any previous copy definition or reading the Defs is no longer available. - for (unsigned Reg : Defs) - ClobberRegister(Reg); } // If MBB doesn't have successors, delete the copies whose defs are not used.