mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
7ac96363aa
Now, flags will result in differing hashes for a given MI. In effect, if you have two instructions with everything identical except for their flags then you should get two different hashes and fewer collisions. Differential Revision: https://reviews.llvm.org/D70479
118 lines
4.2 KiB
C++
118 lines
4.2 KiB
C++
//===---------- 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"
|
|
|
|
using VRegRenameMap = std::map<unsigned, unsigned>;
|
|
|
|
bool VRegRenamer::doVRegRenaming(const VRegRenameMap &VRM) {
|
|
bool Changed = false;
|
|
|
|
for (const auto &E : VRM) {
|
|
Changed = Changed || !MRI.reg_empty(E.first);
|
|
MRI.replaceRegWith(E.first, E.second);
|
|
}
|
|
|
|
return Changed;
|
|
}
|
|
|
|
VRegRenameMap
|
|
VRegRenamer::getVRegRenameMap(const std::vector<NamedVReg> &VRegs) {
|
|
|
|
StringMap<unsigned> VRegNameCollisionMap;
|
|
|
|
auto GetUniqueVRegName = [&VRegNameCollisionMap](const NamedVReg &Reg) {
|
|
if (VRegNameCollisionMap.find(Reg.getName()) == VRegNameCollisionMap.end())
|
|
VRegNameCollisionMap[Reg.getName()] = 0;
|
|
const unsigned Counter = ++VRegNameCollisionMap[Reg.getName()];
|
|
return Reg.getName() + "__" + std::to_string(Counter);
|
|
};
|
|
|
|
VRegRenameMap VRM;
|
|
for (const auto &VReg : VRegs) {
|
|
const unsigned Reg = VReg.getReg();
|
|
VRM[Reg] = createVirtualRegisterWithLowerName(Reg, GetUniqueVRegName(VReg));
|
|
}
|
|
return VRM;
|
|
}
|
|
|
|
std::string VRegRenamer::getInstructionOpcodeHash(MachineInstr &MI) {
|
|
std::string S;
|
|
raw_string_ostream OS(S);
|
|
|
|
// Gets a hashable artifact from a given MachineOperand (ie an unsigned).
|
|
auto GetHashableMO = [this](const MachineOperand &MO) -> unsigned {
|
|
if (MO.isImm())
|
|
return MO.getImm();
|
|
if (MO.isTargetIndex())
|
|
return MO.getOffset() | (MO.getTargetFlags() << 16);
|
|
if (MO.isReg() && Register::isVirtualRegister(MO.getReg()))
|
|
return MRI.getVRegDef(MO.getReg())->getOpcode();
|
|
if (MO.isReg())
|
|
return MO.getReg();
|
|
// TODO:
|
|
// 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 collision but there's enough information
|
|
// (Opcodes,other registers etc) that this will likely not be a problem.
|
|
return 0;
|
|
};
|
|
|
|
SmallVector<unsigned, 16> MIOperands = {MI.getOpcode(), MI.getFlags()};
|
|
llvm::transform(MI.uses(), std::back_inserter(MIOperands), GetHashableMO);
|
|
|
|
auto HashMI = hash_combine_range(MIOperands.begin(), MIOperands.end());
|
|
return std::to_string(HashMI).substr(0, 5);
|
|
}
|
|
|
|
unsigned VRegRenamer::createVirtualRegister(unsigned VReg) {
|
|
assert(Register::isVirtualRegister(VReg) && "Expected Virtual Registers");
|
|
std::string Name = getInstructionOpcodeHash(*MRI.getVRegDef(VReg));
|
|
return createVirtualRegisterWithLowerName(VReg, Name);
|
|
}
|
|
|
|
bool VRegRenamer::renameInstsInMBB(MachineBasicBlock *MBB) {
|
|
std::vector<NamedVReg> VRegs;
|
|
std::string Prefix = "bb" + std::to_string(getCurrentBBNumber()) + "_";
|
|
for (MachineInstr &Candidate : *MBB) {
|
|
// 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)));
|
|
}
|
|
|
|
return VRegs.size() ? doVRegRenaming(getVRegRenameMap(VRegs)) : false;
|
|
}
|
|
|
|
bool VRegRenamer::renameVRegs(MachineBasicBlock *MBB, unsigned BBNum) {
|
|
CurrentBBNumber = BBNum;
|
|
return renameInstsInMBB(MBB);
|
|
}
|
|
|
|
unsigned VRegRenamer::createVirtualRegisterWithLowerName(unsigned VReg,
|
|
StringRef Name) {
|
|
std::string LowerName = Name.lower();
|
|
const TargetRegisterClass *RC = MRI.getRegClassOrNull(VReg);
|
|
return RC ? MRI.createVirtualRegister(RC, LowerName)
|
|
: MRI.createGenericVirtualRegister(MRI.getType(VReg), LowerName);
|
|
}
|