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 using VRegRenameMap = std::map<unsigned, unsigned>; 17 18 bool VRegRenamer::doVRegRenaming(const VRegRenameMap &VRM) { 19 bool Changed = false; 20 21 for (const auto &E : VRM) { 22 Changed = Changed || !MRI.reg_empty(E.first); 23 MRI.replaceRegWith(E.first, E.second); 24 } 25 26 return Changed; 27 } 28 29 VRegRenameMap 30 VRegRenamer::getVRegRenameMap(const std::vector<NamedVReg> &VRegs) { 31 32 StringMap<unsigned> VRegNameCollisionMap; 33 34 auto GetUniqueVRegName = [&VRegNameCollisionMap](const NamedVReg &Reg) { 35 if (VRegNameCollisionMap.find(Reg.getName()) == VRegNameCollisionMap.end()) 36 VRegNameCollisionMap[Reg.getName()] = 0; 37 const unsigned Counter = ++VRegNameCollisionMap[Reg.getName()]; 38 return Reg.getName() + "__" + std::to_string(Counter); 39 }; 40 41 VRegRenameMap VRM; 42 for (const auto &VReg : VRegs) { 43 const unsigned Reg = VReg.getReg(); 44 VRM[Reg] = createVirtualRegisterWithLowerName(Reg, GetUniqueVRegName(VReg)); 45 } 46 return VRM; 47 } 48 49 std::string VRegRenamer::getInstructionOpcodeHash(MachineInstr &MI) { 50 std::string S; 51 raw_string_ostream OS(S); 52 53 // Gets a hashable artifact from a given MachineOperand (ie an unsigned). 54 auto GetHashableMO = [this](const MachineOperand &MO) -> unsigned { 55 if (MO.isImm()) 56 return MO.getImm(); 57 if (MO.isTargetIndex()) 58 return MO.getOffset() | (MO.getTargetFlags() << 16); 59 if (MO.isReg() && Register::isVirtualRegister(MO.getReg())) 60 return MRI.getVRegDef(MO.getReg())->getOpcode(); 61 if (MO.isReg()) 62 return MO.getReg(); 63 // TODO: 64 // We could explicitly handle all the types of the MachineOperand, 65 // here but we can just return a common number until we find a 66 // compelling test case where this is bad. The only side effect here 67 // is contributing to a hash collision but there's enough information 68 // (Opcodes,other registers etc) that this will likely not be a problem. 69 return 0; 70 }; 71 72 SmallVector<unsigned, 16> MIOperands = {MI.getOpcode(), MI.getFlags()}; 73 llvm::transform(MI.uses(), std::back_inserter(MIOperands), GetHashableMO); 74 75 for (const auto *Op : MI.memoperands()) { 76 MIOperands.push_back((unsigned)Op->getSize()); 77 MIOperands.push_back((unsigned)Op->getFlags()); 78 MIOperands.push_back((unsigned)Op->getOffset()); 79 MIOperands.push_back((unsigned)Op->getOrdering()); 80 MIOperands.push_back((unsigned)Op->getAddrSpace()); 81 MIOperands.push_back((unsigned)Op->getSyncScopeID()); 82 MIOperands.push_back((unsigned)Op->getBaseAlignment()); 83 MIOperands.push_back((unsigned)Op->getFailureOrdering()); 84 } 85 86 auto HashMI = hash_combine_range(MIOperands.begin(), MIOperands.end()); 87 return std::to_string(HashMI).substr(0, 5); 88 } 89 90 unsigned VRegRenamer::createVirtualRegister(unsigned VReg) { 91 assert(Register::isVirtualRegister(VReg) && "Expected Virtual Registers"); 92 std::string Name = getInstructionOpcodeHash(*MRI.getVRegDef(VReg)); 93 return createVirtualRegisterWithLowerName(VReg, Name); 94 } 95 96 bool VRegRenamer::renameInstsInMBB(MachineBasicBlock *MBB) { 97 std::vector<NamedVReg> VRegs; 98 std::string Prefix = "bb" + std::to_string(CurrentBBNumber) + "_"; 99 for (MachineInstr &Candidate : *MBB) { 100 // Don't rename stores/branches. 101 if (Candidate.mayStore() || Candidate.isBranch()) 102 continue; 103 if (!Candidate.getNumOperands()) 104 continue; 105 // Look for instructions that define VRegs in operand 0. 106 MachineOperand &MO = Candidate.getOperand(0); 107 // Avoid non regs, instructions defining physical regs. 108 if (!MO.isReg() || !Register::isVirtualRegister(MO.getReg())) 109 continue; 110 VRegs.push_back( 111 NamedVReg(MO.getReg(), Prefix + getInstructionOpcodeHash(Candidate))); 112 } 113 114 return VRegs.size() ? doVRegRenaming(getVRegRenameMap(VRegs)) : false; 115 } 116 117 unsigned VRegRenamer::createVirtualRegisterWithLowerName(unsigned VReg, 118 StringRef Name) { 119 std::string LowerName = Name.lower(); 120 const TargetRegisterClass *RC = MRI.getRegClassOrNull(VReg); 121 return RC ? MRI.createVirtualRegister(RC, LowerName) 122 : MRI.createGenericVirtualRegister(MRI.getType(VReg), LowerName); 123 } 124