LLVM  10.0.0svn
X86DiscriminateMemOps.cpp
Go to the documentation of this file.
1 //===- X86DiscriminateMemOps.cpp - Unique IDs for Mem Ops -----------------===//
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 /// This pass aids profile-driven cache prefetch insertion by ensuring all
10 /// instructions that have a memory operand are distinguishible from each other.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "X86.h"
15 #include "X86InstrBuilder.h"
16 #include "X86InstrInfo.h"
17 #include "X86MachineFunctionInfo.h"
18 #include "X86Subtarget.h"
23 #include "llvm/Support/Debug.h"
25 using namespace llvm;
26 
27 #define DEBUG_TYPE "x86-discriminate-memops"
28 
30  DEBUG_TYPE, cl::init(false),
31  cl::desc("Generate unique debug info for each instruction with a memory "
32  "operand. Should be enabled for profile-drived cache prefetching, "
33  "both in the build of the binary being profiled, as well as in "
34  "the build of the binary consuming the profile."),
35  cl::Hidden);
36 
38  "x86-bypass-prefetch-instructions", cl::init(true),
39  cl::desc("When discriminating instructions with memory operands, ignore "
40  "prefetch instructions. This ensures the other memory operand "
41  "instructions have the same identifiers after inserting "
42  "prefetches, allowing for successive insertions."),
43  cl::Hidden);
44 
45 namespace {
46 
47 using Location = std::pair<StringRef, unsigned>;
48 
49 Location diToLocation(const DILocation *Loc) {
50  return std::make_pair(Loc->getFilename(), Loc->getLine());
51 }
52 
53 /// Ensure each instruction having a memory operand has a distinct <LineNumber,
54 /// Discriminator> pair.
55 void updateDebugInfo(MachineInstr *MI, const DILocation *Loc) {
56  DebugLoc DL(Loc);
57  MI->setDebugLoc(DL);
58 }
59 
60 class X86DiscriminateMemOps : public MachineFunctionPass {
61  bool runOnMachineFunction(MachineFunction &MF) override;
62  StringRef getPassName() const override {
63  return "X86 Discriminate Memory Operands";
64  }
65 
66 public:
67  static char ID;
68 
69  /// Default construct and initialize the pass.
70  X86DiscriminateMemOps();
71 };
72 
73 bool IsPrefetchOpcode(unsigned Opcode) {
74  return Opcode == X86::PREFETCHNTA || Opcode == X86::PREFETCHT0 ||
75  Opcode == X86::PREFETCHT1 || Opcode == X86::PREFETCHT2;
76 }
77 } // end anonymous namespace
78 
79 //===----------------------------------------------------------------------===//
80 // Implementation
81 //===----------------------------------------------------------------------===//
82 
84 
85 /// Default construct and initialize the pass.
86 X86DiscriminateMemOps::X86DiscriminateMemOps() : MachineFunctionPass(ID) {}
87 
88 bool X86DiscriminateMemOps::runOnMachineFunction(MachineFunction &MF) {
90  return false;
91 
93  if (!FDI || !FDI->getUnit()->getDebugInfoForProfiling())
94  return false;
95 
96  // Have a default DILocation, if we find instructions with memops that don't
97  // have any debug info.
98  const DILocation *ReferenceDI =
99  DILocation::get(FDI->getContext(), FDI->getLine(), 0, FDI);
100  assert(ReferenceDI && "ReferenceDI should not be nullptr");
101  DenseMap<Location, unsigned> MemOpDiscriminators;
102  MemOpDiscriminators[diToLocation(ReferenceDI)] = 0;
103 
104  // Figure out the largest discriminator issued for each Location. When we
105  // issue new discriminators, we can thus avoid issuing discriminators
106  // belonging to instructions that don't have memops. This isn't a requirement
107  // for the goals of this pass, however, it avoids unnecessary ambiguity.
108  for (auto &MBB : MF) {
109  for (auto &MI : MBB) {
110  const auto &DI = MI.getDebugLoc();
111  if (!DI)
112  continue;
113  if (BypassPrefetchInstructions && IsPrefetchOpcode(MI.getDesc().Opcode))
114  continue;
115  Location Loc = diToLocation(DI);
116  MemOpDiscriminators[Loc] =
117  std::max(MemOpDiscriminators[Loc], DI->getBaseDiscriminator());
118  }
119  }
120 
121  // Keep track of the discriminators seen at each Location. If an instruction's
122  // DebugInfo has a Location and discriminator we've already seen, replace its
123  // discriminator with a new one, to guarantee uniqueness.
125 
126  bool Changed = false;
127  for (auto &MBB : MF) {
128  for (auto &MI : MBB) {
129  if (X86II::getMemoryOperandNo(MI.getDesc().TSFlags) < 0)
130  continue;
131  if (BypassPrefetchInstructions && IsPrefetchOpcode(MI.getDesc().Opcode))
132  continue;
133  const DILocation *DI = MI.getDebugLoc();
134  bool HasDebug = DI;
135  if (!HasDebug) {
136  DI = ReferenceDI;
137  }
138  Location L = diToLocation(DI);
139  DenseSet<unsigned> &Set = Seen[L];
140  const std::pair<DenseSet<unsigned>::iterator, bool> TryInsert =
141  Set.insert(DI->getBaseDiscriminator());
142  if (!TryInsert.second || !HasDebug) {
143  unsigned BF, DF, CI = 0;
144  DILocation::decodeDiscriminator(DI->getDiscriminator(), BF, DF, CI);
145  Optional<unsigned> EncodedDiscriminator = DILocation::encodeDiscriminator(
146  MemOpDiscriminators[L] + 1, DF, CI);
147 
148  if (!EncodedDiscriminator) {
149  // FIXME(mtrofin): The assumption is that this scenario is infrequent/OK
150  // not to support. If evidence points otherwise, we can explore synthesizeing
151  // unique DIs by adding fake line numbers, or by constructing 64 bit
152  // discriminators.
153  LLVM_DEBUG(dbgs() << "Unable to create a unique discriminator "
154  "for instruction with memory operand in: "
155  << DI->getFilename() << " Line: " << DI->getLine()
156  << " Column: " << DI->getColumn()
157  << ". This is likely due to a large macro expansion. \n");
158  continue;
159  }
160  // Since we were able to encode, bump the MemOpDiscriminators.
161  ++MemOpDiscriminators[L];
162  DI = DI->cloneWithDiscriminator(EncodedDiscriminator.getValue());
163  assert(DI && "DI should not be nullptr");
164  updateDebugInfo(&MI, DI);
165  Changed = true;
166  std::pair<DenseSet<unsigned>::iterator, bool> MustInsert =
167  Set.insert(DI->getBaseDiscriminator());
168  (void)MustInsert; // Silence warning in release build.
169  assert(MustInsert.second && "New discriminator shouldn't be present in set");
170  }
171 
172  // Bump the reference DI to avoid cramming discriminators on line 0.
173  // FIXME(mtrofin): pin ReferenceDI on blocks or first instruction with DI
174  // in a block. It's more consistent than just relying on the last memop
175  // instruction we happened to see.
176  ReferenceDI = DI;
177  }
178  }
179  return Changed;
180 }
181 
183  return new X86DiscriminateMemOps();
184 }
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A debug info location.
Definition: DebugLoc.h:33
static cl::opt< bool > BypassPrefetchInstructions("x86-bypass-prefetch-instructions", cl::init(true), cl::desc("When discriminating instructions with memory operands, ignore " "prefetch instructions. This ensures the other memory operand " "instructions have the same identifiers after inserting " "prefetches, allowing for successive insertions."), cl::Hidden)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Subprogram description.
LLVMContext & getContext() const
Definition: Metadata.h:923
Debug location.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:432
DISubprogram * getSubprogram() const
Get the attached subprogram.
Definition: Metadata.cpp:1522
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:187
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
static cl::opt< bool > EnableDiscriminateMemops(DEBUG_TYPE, cl::init(false), cl::desc("Generate unique debug info for each instruction with a memory " "operand. Should be enabled for profile-drived cache prefetching, " "both in the build of the binary being profiled, as well as in " "the build of the binary consuming the profile."), cl::Hidden)
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:390
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
void setDebugLoc(DebugLoc dl)
Replace current source information with new such.
#define DEBUG_TYPE
Representation of each machine instruction.
Definition: MachineInstr.h:63
unsigned getBaseDiscriminator() const
Returns the base discriminator stored in the discriminator.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const DILocation * cloneWithDiscriminator(unsigned Discriminator) const
Returns a new DILocation with updated Discriminator.
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
FunctionPass * createX86DiscriminateMemOpsPass()
This pass ensures instructions featuring a memory operand have distinctive <LineNumber, Discriminator> (with respect to eachother)
#define LLVM_DEBUG(X)
Definition: Debug.h:122
This file provides the interface for the sampled PGO loader pass.
int getMemoryOperandNo(uint64_t TSFlags)
getMemoryOperandNo - The function returns the MCInst operand # for the first field of the memory oper...
Definition: X86BaseInfo.h:761