LLVM  12.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"
11 #include "llvm/IR/Constants.h"
12 #include "llvm/Support/Debug.h"
13 
14 using namespace llvm;
15 
16 #define DEBUG_TYPE "mir-vregnamer-utils"
17 
18 using VRegRenameMap = std::map<unsigned, unsigned>;
19 
20 bool VRegRenamer::doVRegRenaming(const VRegRenameMap &VRM) {
21  bool Changed = false;
22 
23  for (const auto &E : VRM) {
24  Changed = Changed || !MRI.reg_empty(E.first);
25  MRI.replaceRegWith(E.first, E.second);
26  }
27 
28  return Changed;
29 }
30 
32 VRegRenamer::getVRegRenameMap(const std::vector<NamedVReg> &VRegs) {
33 
34  StringMap<unsigned> VRegNameCollisionMap;
35 
36  auto GetUniqueVRegName = [&VRegNameCollisionMap](const NamedVReg &Reg) {
37  if (VRegNameCollisionMap.find(Reg.getName()) == VRegNameCollisionMap.end())
38  VRegNameCollisionMap[Reg.getName()] = 0;
39  const unsigned Counter = ++VRegNameCollisionMap[Reg.getName()];
40  return Reg.getName() + "__" + std::to_string(Counter);
41  };
42 
43  VRegRenameMap VRM;
44  for (const auto &VReg : VRegs) {
45  const unsigned Reg = VReg.getReg();
46  VRM[Reg] = createVirtualRegisterWithLowerName(Reg, GetUniqueVRegName(VReg));
47  }
48  return VRM;
49 }
50 
51 std::string VRegRenamer::getInstructionOpcodeHash(MachineInstr &MI) {
52  std::string S;
53  raw_string_ostream OS(S);
54 
55  // Gets a hashable artifact from a given MachineOperand (ie an unsigned).
56  auto GetHashableMO = [this](const MachineOperand &MO) -> unsigned {
57  switch (MO.getType()) {
59  return hash_combine(MO.getType(), MO.getTargetFlags(),
60  MO.getCImm()->getZExtValue());
62  return hash_combine(
63  MO.getType(), MO.getTargetFlags(),
64  MO.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
66  if (Register::isVirtualRegister(MO.getReg()))
67  return MRI.getVRegDef(MO.getReg())->getOpcode();
68  return MO.getReg();
70  return MO.getImm();
72  return MO.getOffset() | (MO.getTargetFlags() << 16);
76  return llvm::hash_value(MO);
77 
78  // We could explicitly handle all the types of the MachineOperand,
79  // here but we can just return a common number until we find a
80  // compelling test case where this is bad. The only side effect here
81  // is contributing to a hash collision but there's enough information
82  // (Opcodes,other registers etc) that this will likely not be a problem.
83 
84  // TODO: Handle the following Index/ID/Predicate cases. They can
85  // be hashed on in a stable manner.
89 
90  // In the cases below we havn't found a way to produce an artifact that will
91  // result in a stable hash, in most cases because they are pointers. We want
92  // stable hashes because we want the hash to be the same run to run.
102  return 0;
103  }
104  llvm_unreachable("Unexpected MachineOperandType.");
105  };
106 
107  SmallVector<unsigned, 16> MIOperands = {MI.getOpcode(), MI.getFlags()};
108  llvm::transform(MI.uses(), std::back_inserter(MIOperands), GetHashableMO);
109 
110  for (const auto *Op : MI.memoperands()) {
111  MIOperands.push_back((unsigned)Op->getSize());
112  MIOperands.push_back((unsigned)Op->getFlags());
113  MIOperands.push_back((unsigned)Op->getOffset());
114  MIOperands.push_back((unsigned)Op->getOrdering());
115  MIOperands.push_back((unsigned)Op->getAddrSpace());
116  MIOperands.push_back((unsigned)Op->getSyncScopeID());
117  MIOperands.push_back((unsigned)Op->getBaseAlign().value());
118  MIOperands.push_back((unsigned)Op->getFailureOrdering());
119  }
120 
121  auto HashMI = hash_combine_range(MIOperands.begin(), MIOperands.end());
122  return std::to_string(HashMI).substr(0, 5);
123 }
124 
125 unsigned VRegRenamer::createVirtualRegister(unsigned VReg) {
126  assert(Register::isVirtualRegister(VReg) && "Expected Virtual Registers");
127  std::string Name = getInstructionOpcodeHash(*MRI.getVRegDef(VReg));
128  return createVirtualRegisterWithLowerName(VReg, Name);
129 }
130 
131 bool VRegRenamer::renameInstsInMBB(MachineBasicBlock *MBB) {
132  std::vector<NamedVReg> VRegs;
133  std::string Prefix = "bb" + std::to_string(CurrentBBNumber) + "_";
134  for (MachineInstr &Candidate : *MBB) {
135  // Don't rename stores/branches.
136  if (Candidate.mayStore() || Candidate.isBranch())
137  continue;
138  if (!Candidate.getNumOperands())
139  continue;
140  // Look for instructions that define VRegs in operand 0.
141  MachineOperand &MO = Candidate.getOperand(0);
142  // Avoid non regs, instructions defining physical regs.
143  if (!MO.isReg() || !Register::isVirtualRegister(MO.getReg()))
144  continue;
145  VRegs.push_back(
146  NamedVReg(MO.getReg(), Prefix + getInstructionOpcodeHash(Candidate)));
147  }
148 
149  return VRegs.size() ? doVRegRenaming(getVRegRenameMap(VRegs)) : false;
150 }
151 
152 unsigned VRegRenamer::createVirtualRegisterWithLowerName(unsigned VReg,
153  StringRef Name) {
154  std::string LowerName = Name.lower();
155  const TargetRegisterClass *RC = MRI.getRegClassOrNull(VReg);
156  return RC ? MRI.createVirtualRegister(RC, LowerName)
157  : MRI.createGenericVirtualRegister(MRI.getType(VReg), LowerName);
158 }
This class represents lattice values for constants.
Definition: AllocatorList.h:23
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
Definition: MachineInstr.h:603
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
void push_back(const T &Elt)
Definition: SmallVector.h:246
Address of indexed Jump Table for switch.
unsigned Reg
iterator find(StringRef Key)
Definition: StringMap.h:216
bool reg_empty(Register RegNo) const
reg_empty - Return true if there are no instructions using or defining the specified register (it may...
MachineBasicBlock reference.
Mask of live-out registers.
MachineBasicBlock & MBB
Mask of preserved registers.
MCCFIInstruction index.
Target-dependent index+offset operand.
static Optional< unsigned > getOpcode(ArrayRef< VPValue *> Values)
Returns the opcode of Values or ~0 if they do not all agree.
Definition: VPlanSLP.cpp:196
Name of external global symbol.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:456
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet...
Immediate >64bit operand.
std::map< unsigned, unsigned > VRegRenameMap
hash_code hash_value(const APFloat &Arg)
See friend declarations above.
Definition: APFloat.cpp:4797
Address of a global value.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
Definition: MachineInstr.h:627
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
Address of a basic block.
void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Generic predicate for ISel.
MachineOperand class - Representation of each machine instruction operand.
MCSymbol reference (for debug/eh info)
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition: Hashing.h:599
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
Definition: Hashing.h:477
Representation of each machine instruction.
Definition: MachineInstr.h:62
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
Abstract Stack Frame Index.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere...
Definition: STLExtras.h:1581
uint16_t getFlags() const
Return the MI flags bitvector.
Definition: MachineInstr.h:316
const std::string to_string(const T &Value)
Definition: ScopedPrinter.h:61
LLVM_NODISCARD std::string lower() const
Definition: StringRef.cpp:108
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:521
Floating-point immediate operand.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:71
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
Address of indexed Constant in Constant Pool.
Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
Register getReg() const
getReg - Returns the register number.
Other IR Constant for ISel (shuffle masks)
iterator end()
Definition: StringMap.h:203
Metadata reference (for debug info)