LLVM  14.0.0git
MIRVRegNamerUtils.cpp
Go to the documentation of this file.
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"
12 #include "llvm/IR/Constants.h"
13 #include "llvm/Support/Debug.h"
14 
15 using namespace llvm;
16 
17 #define DEBUG_TYPE "mir-vregnamer-utils"
18 
19 static cl::opt<bool>
20  UseStableNamerHash("mir-vreg-namer-use-stable-hash", cl::init(false),
21  cl::Hidden,
22  cl::desc("Use Stable Hashing for MIR VReg Renaming"));
23 
24 using VRegRenameMap = std::map<unsigned, unsigned>;
25 
26 bool VRegRenamer::doVRegRenaming(const VRegRenameMap &VRM) {
27  bool Changed = false;
28 
29  for (const auto &E : VRM) {
30  Changed = Changed || !MRI.reg_empty(E.first);
31  MRI.replaceRegWith(E.first, E.second);
32  }
33 
34  return Changed;
35 }
36 
38 VRegRenamer::getVRegRenameMap(const std::vector<NamedVReg> &VRegs) {
39 
40  StringMap<unsigned> VRegNameCollisionMap;
41 
42  auto GetUniqueVRegName = [&VRegNameCollisionMap](const NamedVReg &Reg) {
43  if (VRegNameCollisionMap.find(Reg.getName()) == VRegNameCollisionMap.end())
44  VRegNameCollisionMap[Reg.getName()] = 0;
45  const unsigned Counter = ++VRegNameCollisionMap[Reg.getName()];
46  return Reg.getName() + "__" + std::to_string(Counter);
47  };
48 
49  VRegRenameMap VRM;
50  for (const auto &VReg : VRegs) {
51  const unsigned Reg = VReg.getReg();
52  VRM[Reg] = createVirtualRegisterWithLowerName(Reg, GetUniqueVRegName(VReg));
53  }
54  return VRM;
55 }
56 
57 std::string VRegRenamer::getInstructionOpcodeHash(MachineInstr &MI) {
58  std::string S;
60 
61  if (UseStableNamerHash) {
62  auto Hash = stableHashValue(MI, /* HashVRegs */ true,
63  /* HashConstantPoolIndices */ true,
64  /* HashMemOperands */ true);
65  assert(Hash && "Expected non-zero Hash");
66  return std::to_string(Hash).substr(0, 5);
67  }
68 
69  // Gets a hashable artifact from a given MachineOperand (ie an unsigned).
70  auto GetHashableMO = [this](const MachineOperand &MO) -> unsigned {
71  switch (MO.getType()) {
73  return hash_combine(MO.getType(), MO.getTargetFlags(),
74  MO.getCImm()->getZExtValue());
76  return hash_combine(
77  MO.getType(), MO.getTargetFlags(),
78  MO.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
80  if (Register::isVirtualRegister(MO.getReg()))
81  return MRI.getVRegDef(MO.getReg())->getOpcode();
82  return MO.getReg();
84  return MO.getImm();
86  return MO.getOffset() | (MO.getTargetFlags() << 16);
90  return llvm::hash_value(MO);
91 
92  // We could explicitly handle all the types of the MachineOperand,
93  // here but we can just return a common number until we find a
94  // compelling test case where this is bad. The only side effect here
95  // is contributing to a hash collision but there's enough information
96  // (Opcodes,other registers etc) that this will likely not be a problem.
97 
98  // TODO: Handle the following Index/ID/Predicate cases. They can
99  // be hashed on in a stable manner.
103 
104  // In the cases below we havn't found a way to produce an artifact that will
105  // result in a stable hash, in most cases because they are pointers. We want
106  // stable hashes because we want the hash to be the same run to run.
116  return 0;
117  }
118  llvm_unreachable("Unexpected MachineOperandType.");
119  };
120 
121  SmallVector<unsigned, 16> MIOperands = {MI.getOpcode(), MI.getFlags()};
122  llvm::transform(MI.uses(), std::back_inserter(MIOperands), GetHashableMO);
123 
124  for (const auto *Op : MI.memoperands()) {
125  MIOperands.push_back((unsigned)Op->getSize());
126  MIOperands.push_back((unsigned)Op->getFlags());
127  MIOperands.push_back((unsigned)Op->getOffset());
128  MIOperands.push_back((unsigned)Op->getSuccessOrdering());
129  MIOperands.push_back((unsigned)Op->getAddrSpace());
130  MIOperands.push_back((unsigned)Op->getSyncScopeID());
131  MIOperands.push_back((unsigned)Op->getBaseAlign().value());
132  MIOperands.push_back((unsigned)Op->getFailureOrdering());
133  }
134 
135  auto HashMI = hash_combine_range(MIOperands.begin(), MIOperands.end());
136  return std::to_string(HashMI).substr(0, 5);
137 }
138 
139 unsigned VRegRenamer::createVirtualRegister(unsigned VReg) {
140  assert(Register::isVirtualRegister(VReg) && "Expected Virtual Registers");
141  std::string Name = getInstructionOpcodeHash(*MRI.getVRegDef(VReg));
142  return createVirtualRegisterWithLowerName(VReg, Name);
143 }
144 
145 bool VRegRenamer::renameInstsInMBB(MachineBasicBlock *MBB) {
146  std::vector<NamedVReg> VRegs;
147  std::string Prefix = "bb" + std::to_string(CurrentBBNumber) + "_";
148  for (MachineInstr &Candidate : *MBB) {
149  // Don't rename stores/branches.
150  if (Candidate.mayStore() || Candidate.isBranch())
151  continue;
152  if (!Candidate.getNumOperands())
153  continue;
154  // Look for instructions that define VRegs in operand 0.
155  MachineOperand &MO = Candidate.getOperand(0);
156  // Avoid non regs, instructions defining physical regs.
157  if (!MO.isReg() || !Register::isVirtualRegister(MO.getReg()))
158  continue;
159  VRegs.push_back(
160  NamedVReg(MO.getReg(), Prefix + getInstructionOpcodeHash(Candidate)));
161  }
162 
163  return VRegs.size() ? doVRegRenaming(getVRegRenameMap(VRegs)) : false;
164 }
165 
166 unsigned VRegRenamer::createVirtualRegisterWithLowerName(unsigned VReg,
167  StringRef Name) {
168  std::string LowerName = Name.lower();
169  const TargetRegisterClass *RC = MRI.getRegClassOrNull(VReg);
170  return RC ? MRI.createVirtualRegister(RC, LowerName)
171  : MRI.createGenericVirtualRegister(MRI.getType(VReg), LowerName);
172 }
llvm::MachineOperand::MO_BlockAddress
@ MO_BlockAddress
Address of a basic block.
Definition: MachineOperand.h:63
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:105
llvm::MachineOperand::MO_Immediate
@ MO_Immediate
Immediate operand.
Definition: MachineOperand.h:53
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1566
llvm::MachineRegisterInfo::createVirtualRegister
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Definition: MachineRegisterInfo.cpp:158
llvm::cl::Prefix
@ Prefix
Definition: CommandLine.h:164
llvm::MachineOperand::MO_ShuffleMask
@ MO_ShuffleMask
Other IR Constant for ISel (shuffle masks)
Definition: MachineOperand.h:71
llvm::MachineOperand::MO_RegisterLiveOut
@ MO_RegisterLiveOut
Mask of live-out registers.
Definition: MachineOperand.h:65
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:625
MIRVRegNamerUtils.h
llvm::SmallVector< unsigned, 16 >
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:143
llvm::StringMap::end
iterator end()
Definition: StringMap.h:203
llvm::MachineOperand::MO_CFIIndex
@ MO_CFIIndex
MCCFIInstruction index.
Definition: MachineOperand.h:68
llvm::StringMap::find
iterator find(StringRef Key)
Definition: StringMap.h:216
llvm::hash_value
hash_code hash_value(const APFloat &Arg)
See friend declarations above.
Definition: APFloat.cpp:4821
llvm::MachineOperand::MO_Register
@ MO_Register
Register operand.
Definition: MachineOperand.h:52
MachineRegisterInfo.h
Constants.h
llvm::MachineOperand::MO_GlobalAddress
@ MO_GlobalAddress
Address of a global value.
Definition: MachineOperand.h:62
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::MachineOperand::MO_FrameIndex
@ MO_FrameIndex
Abstract Stack Frame Index.
Definition: MachineOperand.h:57
llvm::TargetRegisterClass
Definition: TargetRegisterInfo.h:46
llvm::stableHashValue
stable_hash stableHashValue(const MachineOperand &MO)
Definition: MachineStableHash.cpp:62
false
Definition: StackSlotColoring.cpp:142
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
VRegRenameMap
std::map< unsigned, unsigned > VRegRenameMap
Definition: MIRVRegNamerUtils.cpp:24
MachineStableHash.h
llvm::MachineRegisterInfo::getVRegDef
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
Definition: MachineRegisterInfo.cpp:400
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
llvm::StringMap< unsigned >
llvm::cl::opt< bool >
llvm::MachineOperand::MO_Metadata
@ MO_Metadata
Metadata reference (for debug info)
Definition: MachineOperand.h:66
llvm::MachineOperand::isReg
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Definition: MachineOperand.h:321
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
llvm::MachineOperand::MO_Predicate
@ MO_Predicate
Generic predicate for ISel.
Definition: MachineOperand.h:70
llvm::MachineOperand::MO_MCSymbol
@ MO_MCSymbol
MCSymbol reference (for debug/eh info)
Definition: MachineOperand.h:67
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:441
llvm::Register::isVirtualRegister
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:71
llvm::MachineRegisterInfo::getRegClassOrNull
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
Definition: MachineRegisterInfo.h:651
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MachineOperand::MO_TargetIndex
@ MO_TargetIndex
Target-dependent index+offset operand.
Definition: MachineOperand.h:59
llvm::MachineOperand::MO_FPImmediate
@ MO_FPImmediate
Floating-point immediate operand.
Definition: MachineOperand.h:55
llvm::MachineRegisterInfo::createGenericVirtualRegister
Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
Definition: MachineRegisterInfo.cpp:188
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:360
llvm::MachineOperand::MO_JumpTableIndex
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
Definition: MachineOperand.h:60
llvm::MachineOperand::MO_CImmediate
@ MO_CImmediate
Immediate >64bit operand.
Definition: MachineOperand.h:54
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::MachineInstr::getOpcode
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:489
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
llvm::transform
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
Definition: STLExtras.h:1648
llvm::MachineOperand::MO_MachineBasicBlock
@ MO_MachineBasicBlock
MachineBasicBlock reference.
Definition: MachineOperand.h:56
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::MachineOperand::MO_IntrinsicID
@ MO_IntrinsicID
Intrinsic ID for ISel.
Definition: MachineOperand.h:69
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::MachineRegisterInfo::replaceRegWith
void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Definition: MachineRegisterInfo.cpp:380
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:324
llvm::MachineOperand::MO_ExternalSymbol
@ MO_ExternalSymbol
Name of external global symbol.
Definition: MachineOperand.h:61
llvm::MachineRegisterInfo::reg_empty
bool reg_empty(Register RegNo) const
reg_empty - Return true if there are no instructions using or defining the specified register (it may...
Definition: MachineRegisterInfo.h:323
llvm::MachineRegisterInfo::getType
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
Definition: MachineRegisterInfo.h:732
llvm::hash_combine
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition: Hashing.h:605
llvm::hash_combine_range
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
Definition: Hashing.h:483
llvm::to_string
std::string to_string(const T &Value)
Definition: ScopedPrinter.h:63
llvm::MachineOperand::MO_RegisterMask
@ MO_RegisterMask
Mask of preserved registers.
Definition: MachineOperand.h:64
llvm::cl::desc
Definition: CommandLine.h:412
UseStableNamerHash
static cl::opt< bool > UseStableNamerHash("mir-vreg-namer-use-stable-hash", cl::init(false), cl::Hidden, cl::desc("Use Stable Hashing for MIR VReg Renaming"))
Debug.h
llvm::MachineOperand::MO_ConstantPoolIndex
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
Definition: MachineOperand.h:58