MIRVRegNamerUtils.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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. #include "MIRVRegNamerUtils.h"
  9. #include "llvm/CodeGen/MachineRegisterInfo.h"
  10. #include "llvm/CodeGen/MachineStableHash.h"
  11. #include "llvm/IR/Constants.h"
  12. using namespace llvm;
  13. #define DEBUG_TYPE "mir-vregnamer-utils"
  14. static cl::opt<bool>
  15. UseStableNamerHash("mir-vreg-namer-use-stable-hash", cl::init(false),
  16. cl::Hidden,
  17. cl::desc("Use Stable Hashing for MIR VReg Renaming"));
  18. using VRegRenameMap = std::map<unsigned, unsigned>;
  19. bool VRegRenamer::doVRegRenaming(const VRegRenameMap &VRM) {
  20. bool Changed = false;
  21. for (const auto &E : VRM) {
  22. Changed = Changed || !MRI.reg_empty(E.first);
  23. MRI.replaceRegWith(E.first, E.second);
  24. }
  25. return Changed;
  26. }
  27. VRegRenameMap
  28. VRegRenamer::getVRegRenameMap(const std::vector<NamedVReg> &VRegs) {
  29. StringMap<unsigned> VRegNameCollisionMap;
  30. auto GetUniqueVRegName = [&VRegNameCollisionMap](const NamedVReg &Reg) {
  31. if (VRegNameCollisionMap.find(Reg.getName()) == VRegNameCollisionMap.end())
  32. VRegNameCollisionMap[Reg.getName()] = 0;
  33. const unsigned Counter = ++VRegNameCollisionMap[Reg.getName()];
  34. return Reg.getName() + "__" + std::to_string(Counter);
  35. };
  36. VRegRenameMap VRM;
  37. for (const auto &VReg : VRegs) {
  38. const unsigned Reg = VReg.getReg();
  39. VRM[Reg] = createVirtualRegisterWithLowerName(Reg, GetUniqueVRegName(VReg));
  40. }
  41. return VRM;
  42. }
  43. std::string VRegRenamer::getInstructionOpcodeHash(MachineInstr &MI) {
  44. std::string S;
  45. raw_string_ostream OS(S);
  46. if (UseStableNamerHash) {
  47. auto Hash = stableHashValue(MI, /* HashVRegs */ true,
  48. /* HashConstantPoolIndices */ true,
  49. /* HashMemOperands */ true);
  50. assert(Hash && "Expected non-zero Hash");
  51. OS << format_hex_no_prefix(Hash, 16, true);
  52. return OS.str();
  53. }
  54. // Gets a hashable artifact from a given MachineOperand (ie an unsigned).
  55. auto GetHashableMO = [this](const MachineOperand &MO) -> unsigned {
  56. switch (MO.getType()) {
  57. case MachineOperand::MO_CImmediate:
  58. return hash_combine(MO.getType(), MO.getTargetFlags(),
  59. MO.getCImm()->getZExtValue());
  60. case MachineOperand::MO_FPImmediate:
  61. return hash_combine(
  62. MO.getType(), MO.getTargetFlags(),
  63. MO.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
  64. case MachineOperand::MO_Register:
  65. if (MO.getReg().isVirtual())
  66. return MRI.getVRegDef(MO.getReg())->getOpcode();
  67. return MO.getReg();
  68. case MachineOperand::MO_Immediate:
  69. return MO.getImm();
  70. case MachineOperand::MO_TargetIndex:
  71. return MO.getOffset() | (MO.getTargetFlags() << 16);
  72. case MachineOperand::MO_FrameIndex:
  73. case MachineOperand::MO_ConstantPoolIndex:
  74. case MachineOperand::MO_JumpTableIndex:
  75. return llvm::hash_value(MO);
  76. // We could explicitly handle all the types of the MachineOperand,
  77. // here but we can just return a common number until we find a
  78. // compelling test case where this is bad. The only side effect here
  79. // is contributing to a hash collision but there's enough information
  80. // (Opcodes,other registers etc) that this will likely not be a problem.
  81. // TODO: Handle the following Index/ID/Predicate cases. They can
  82. // be hashed on in a stable manner.
  83. case MachineOperand::MO_CFIIndex:
  84. case MachineOperand::MO_IntrinsicID:
  85. case MachineOperand::MO_Predicate:
  86. // In the cases below we havn't found a way to produce an artifact that will
  87. // result in a stable hash, in most cases because they are pointers. We want
  88. // stable hashes because we want the hash to be the same run to run.
  89. case MachineOperand::MO_MachineBasicBlock:
  90. case MachineOperand::MO_ExternalSymbol:
  91. case MachineOperand::MO_GlobalAddress:
  92. case MachineOperand::MO_BlockAddress:
  93. case MachineOperand::MO_RegisterMask:
  94. case MachineOperand::MO_RegisterLiveOut:
  95. case MachineOperand::MO_Metadata:
  96. case MachineOperand::MO_MCSymbol:
  97. case MachineOperand::MO_ShuffleMask:
  98. case MachineOperand::MO_DbgInstrRef:
  99. return 0;
  100. }
  101. llvm_unreachable("Unexpected MachineOperandType.");
  102. };
  103. SmallVector<unsigned, 16> MIOperands = {MI.getOpcode(), MI.getFlags()};
  104. llvm::transform(MI.uses(), std::back_inserter(MIOperands), GetHashableMO);
  105. for (const auto *Op : MI.memoperands()) {
  106. MIOperands.push_back((unsigned)Op->getSize());
  107. MIOperands.push_back((unsigned)Op->getFlags());
  108. MIOperands.push_back((unsigned)Op->getOffset());
  109. MIOperands.push_back((unsigned)Op->getSuccessOrdering());
  110. MIOperands.push_back((unsigned)Op->getAddrSpace());
  111. MIOperands.push_back((unsigned)Op->getSyncScopeID());
  112. MIOperands.push_back((unsigned)Op->getBaseAlign().value());
  113. MIOperands.push_back((unsigned)Op->getFailureOrdering());
  114. }
  115. auto HashMI = hash_combine_range(MIOperands.begin(), MIOperands.end());
  116. OS << format_hex_no_prefix(HashMI, 16, true);
  117. return OS.str();
  118. }
  119. unsigned VRegRenamer::createVirtualRegister(unsigned VReg) {
  120. assert(Register::isVirtualRegister(VReg) && "Expected Virtual Registers");
  121. std::string Name = getInstructionOpcodeHash(*MRI.getVRegDef(VReg));
  122. return createVirtualRegisterWithLowerName(VReg, Name);
  123. }
  124. bool VRegRenamer::renameInstsInMBB(MachineBasicBlock *MBB) {
  125. std::vector<NamedVReg> VRegs;
  126. std::string Prefix = "bb" + std::to_string(CurrentBBNumber) + "_";
  127. for (MachineInstr &Candidate : *MBB) {
  128. // Don't rename stores/branches.
  129. if (Candidate.mayStore() || Candidate.isBranch())
  130. continue;
  131. if (!Candidate.getNumOperands())
  132. continue;
  133. // Look for instructions that define VRegs in operand 0.
  134. MachineOperand &MO = Candidate.getOperand(0);
  135. // Avoid non regs, instructions defining physical regs.
  136. if (!MO.isReg() || !MO.getReg().isVirtual())
  137. continue;
  138. VRegs.push_back(
  139. NamedVReg(MO.getReg(), Prefix + getInstructionOpcodeHash(Candidate)));
  140. }
  141. return VRegs.size() ? doVRegRenaming(getVRegRenameMap(VRegs)) : false;
  142. }
  143. unsigned VRegRenamer::createVirtualRegisterWithLowerName(unsigned VReg,
  144. StringRef Name) {
  145. std::string LowerName = Name.lower();
  146. const TargetRegisterClass *RC = MRI.getRegClassOrNull(VReg);
  147. return RC ? MRI.createVirtualRegister(RC, LowerName)
  148. : MRI.createGenericVirtualRegister(MRI.getType(VReg), LowerName);
  149. }