//===---------- MIRVRegNamerUtils.cpp - MIR VReg Renaming Utilities -------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "MIRVRegNamerUtils.h" #include "llvm/Support/Debug.h" using namespace llvm; #define DEBUG_TYPE "mir-vregnamer-utils" bool VRegRenamer::doVRegRenaming( const std::map &VRegRenameMap) { bool Changed = false; for (auto I = VRegRenameMap.begin(), E = VRegRenameMap.end(); I != E; ++I) { auto VReg = I->first; auto Rename = I->second; std::vector RenameMOs; for (auto &MO : MRI.reg_operands(VReg)) { RenameMOs.push_back(&MO); } for (auto *MO : RenameMOs) { Changed = true; MO->setReg(Rename); if (!MO->isDef()) MO->setIsKill(false); } } return Changed; } std::map VRegRenamer::getVRegRenameMap(const std::vector &VRegs) { std::map VRegRenameMap; std::map VRegNameCollisionMap; auto GetUniqueVRegName = [&VRegNameCollisionMap](const NamedVReg &Reg) -> std::string { auto It = VRegNameCollisionMap.find(Reg.getName()); unsigned Counter = 0; if (It != VRegNameCollisionMap.end()) { Counter = It->second; } ++Counter; VRegNameCollisionMap[Reg.getName()] = Counter; return Reg.getName() + "__" + std::to_string(Counter); }; for (auto &Vreg : VRegs) { auto Reg = Vreg.getReg(); assert(Register::isVirtualRegister(Reg) && "Expecting Virtual Registers Only"); auto NewNameForReg = GetUniqueVRegName(Vreg); auto Rename = createVirtualRegisterWithName(Reg, NewNameForReg); VRegRenameMap.insert(std::pair(Reg, Rename)); } return VRegRenameMap; } std::string VRegRenamer::getInstructionOpcodeHash(MachineInstr &MI) { std::string S; raw_string_ostream OS(S); auto HashOperand = [this](const MachineOperand &MO) -> unsigned { if (MO.isImm()) return MO.getImm(); if (MO.isTargetIndex()) return MO.getOffset() | (MO.getTargetFlags() << 16); if (MO.isReg()) { return Register::isVirtualRegister(MO.getReg()) ? MRI.getVRegDef(MO.getReg())->getOpcode() : (unsigned)MO.getReg(); } // We could explicitly handle all the types of the MachineOperand, // here but we can just return a common number until we find a // compelling test case where this is bad. The only side effect here // is contributing to a hash collission but there's enough information // (Opcodes,other registers etc) that this will likely not be a problem. return 0; }; SmallVector MIOperands; MIOperands.push_back(MI.getOpcode()); for (auto &Op : MI.uses()) { MIOperands.push_back(HashOperand(Op)); } auto HashMI = hash_combine_range(MIOperands.begin(), MIOperands.end()); return std::to_string(HashMI).substr(0, 5); } unsigned VRegRenamer::createVirtualRegister(unsigned VReg) { return createVirtualRegisterWithName( VReg, getInstructionOpcodeHash(*MRI.getVRegDef(VReg))); } bool VRegRenamer::renameInstsInMBB(MachineBasicBlock *MBB) { std::vector VRegs; std::string Prefix = "bb" + std::to_string(getCurrentBBNumber()) + "_"; for (auto &MII : *MBB) { MachineInstr &Candidate = MII; // Don't rename stores/branches. if (Candidate.mayStore() || Candidate.isBranch()) continue; if (!Candidate.getNumOperands()) continue; // Look for instructions that define VRegs in operand 0. MachineOperand &MO = Candidate.getOperand(0); // Avoid non regs, instructions defining physical regs. if (!MO.isReg() || !Register::isVirtualRegister(MO.getReg())) continue; VRegs.push_back( NamedVReg(MO.getReg(), Prefix + getInstructionOpcodeHash(Candidate))); } // If we have populated no vregs to rename then bail. // The rest of this function does the vreg remaping. if (VRegs.size() == 0) return false; auto VRegRenameMap = getVRegRenameMap(VRegs); return doVRegRenaming(VRegRenameMap); } bool VRegRenamer::renameVRegs(MachineBasicBlock *MBB, unsigned BBNum) { CurrentBBNumber = BBNum; return renameInstsInMBB(MBB); } unsigned VRegRenamer::createVirtualRegisterWithName(unsigned VReg, const std::string &Name) { std::string Temp(Name); std::transform(Temp.begin(), Temp.end(), Temp.begin(), ::tolower); if (auto RC = MRI.getRegClassOrNull(VReg)) return MRI.createVirtualRegister(RC, Temp); return MRI.createGenericVirtualRegister(MRI.getType(VReg), Name); }