1 //===---------- MIRVRegNamerUtils.cpp - MIR VReg Renaming Utilities -------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "MIRVRegNamerUtils.h" 10 #include "llvm/Support/Debug.h" 11 12 using namespace llvm; 13 14 #define DEBUG_TYPE "mir-vregnamer-utils" 15 16 bool VRegRenamer::doVRegRenaming( 17 const std::map<unsigned, unsigned> &VRegRenameMap) { 18 bool Changed = false; 19 for (auto I = VRegRenameMap.begin(), E = VRegRenameMap.end(); I != E; ++I) { 20 21 auto VReg = I->first; 22 auto Rename = I->second; 23 24 std::vector<MachineOperand *> RenameMOs; 25 for (auto &MO : MRI.reg_operands(VReg)) { 26 RenameMOs.push_back(&MO); 27 } 28 29 for (auto *MO : RenameMOs) { 30 Changed = true; 31 MO->setReg(Rename); 32 33 if (!MO->isDef()) 34 MO->setIsKill(false); 35 } 36 } 37 38 return Changed; 39 } 40 41 std::map<unsigned, unsigned> 42 VRegRenamer::getVRegRenameMap(const std::vector<NamedVReg> &VRegs) { 43 std::map<unsigned, unsigned> VRegRenameMap; 44 45 std::map<std::string, unsigned> VRegNameCollisionMap; 46 47 auto GetUniqueVRegName = 48 [&VRegNameCollisionMap](const NamedVReg &Reg) -> std::string { 49 auto It = VRegNameCollisionMap.find(Reg.getName()); 50 unsigned Counter = 0; 51 if (It != VRegNameCollisionMap.end()) { 52 Counter = It->second; 53 } 54 ++Counter; 55 VRegNameCollisionMap[Reg.getName()] = Counter; 56 return Reg.getName() + "__" + std::to_string(Counter); 57 }; 58 59 for (auto &Vreg : VRegs) { 60 auto Reg = Vreg.getReg(); 61 assert(Register::isVirtualRegister(Reg) && 62 "Expecting Virtual Registers Only"); 63 auto NewNameForReg = GetUniqueVRegName(Vreg); 64 auto Rename = createVirtualRegisterWithName(Reg, NewNameForReg); 65 66 VRegRenameMap.insert(std::pair<unsigned, unsigned>(Reg, Rename)); 67 } 68 return VRegRenameMap; 69 } 70 71 std::string VRegRenamer::getInstructionOpcodeHash(MachineInstr &MI) { 72 std::string S; 73 raw_string_ostream OS(S); 74 auto HashOperand = [this](const MachineOperand &MO) -> unsigned { 75 if (MO.isImm()) 76 return MO.getImm(); 77 if (MO.isTargetIndex()) 78 return MO.getOffset() | (MO.getTargetFlags() << 16); 79 if (MO.isReg()) { 80 return Register::isVirtualRegister(MO.getReg()) 81 ? MRI.getVRegDef(MO.getReg())->getOpcode() 82 : (unsigned)MO.getReg(); 83 } 84 // We could explicitly handle all the types of the MachineOperand, 85 // here but we can just return a common number until we find a 86 // compelling test case where this is bad. The only side effect here 87 // is contributing to a hash collission but there's enough information 88 // (Opcodes,other registers etc) that this will likely not be a problem. 89 return 0; 90 }; 91 SmallVector<unsigned, 16> MIOperands; 92 MIOperands.push_back(MI.getOpcode()); 93 for (auto &Op : MI.uses()) { 94 MIOperands.push_back(HashOperand(Op)); 95 } 96 auto HashMI = hash_combine_range(MIOperands.begin(), MIOperands.end()); 97 return std::to_string(HashMI).substr(0, 5); 98 } 99 100 unsigned VRegRenamer::createVirtualRegister(unsigned VReg) { 101 return createVirtualRegisterWithName( 102 VReg, getInstructionOpcodeHash(*MRI.getVRegDef(VReg))); 103 } 104 105 bool VRegRenamer::renameInstsInMBB(MachineBasicBlock *MBB) { 106 std::vector<NamedVReg> VRegs; 107 std::string Prefix = "bb" + std::to_string(getCurrentBBNumber()) + "_"; 108 for (auto &MII : *MBB) { 109 MachineInstr &Candidate = MII; 110 // Don't rename stores/branches. 111 if (Candidate.mayStore() || Candidate.isBranch()) 112 continue; 113 if (!Candidate.getNumOperands()) 114 continue; 115 // Look for instructions that define VRegs in operand 0. 116 MachineOperand &MO = Candidate.getOperand(0); 117 // Avoid non regs, instructions defining physical regs. 118 if (!MO.isReg() || !Register::isVirtualRegister(MO.getReg())) 119 continue; 120 VRegs.push_back( 121 NamedVReg(MO.getReg(), Prefix + getInstructionOpcodeHash(Candidate))); 122 } 123 124 // If we have populated no vregs to rename then bail. 125 // The rest of this function does the vreg remaping. 126 if (VRegs.size() == 0) 127 return false; 128 129 auto VRegRenameMap = getVRegRenameMap(VRegs); 130 return doVRegRenaming(VRegRenameMap); 131 } 132 133 bool VRegRenamer::renameVRegs(MachineBasicBlock *MBB, unsigned BBNum) { 134 CurrentBBNumber = BBNum; 135 return renameInstsInMBB(MBB); 136 } 137 138 unsigned VRegRenamer::createVirtualRegisterWithName(unsigned VReg, 139 const std::string &Name) { 140 std::string Temp(Name); 141 std::transform(Temp.begin(), Temp.end(), Temp.begin(), ::tolower); 142 if (auto RC = MRI.getRegClassOrNull(VReg)) 143 return MRI.createVirtualRegister(RC, Temp); 144 return MRI.createGenericVirtualRegister(MRI.getType(VReg), Name); 145 } 146