LLVM  9.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 
37 namespace {
38 
39 using Location = std::pair<StringRef, unsigned>;
40 
41 Location diToLocation(const DILocation *Loc) {
42  return std::make_pair(Loc->getFilename(), Loc->getLine());
43 }
44 
45 /// Ensure each instruction having a memory operand has a distinct <LineNumber,
46 /// Discriminator> pair.
47 void updateDebugInfo(MachineInstr *MI, const DILocation *Loc) {
48  DebugLoc DL(Loc);
49  MI->setDebugLoc(DL);
50 }
51 
52 class X86DiscriminateMemOps : public MachineFunctionPass {
53  bool runOnMachineFunction(MachineFunction &MF) override;
54  StringRef getPassName() const override {
55  return "X86 Discriminate Memory Operands";
56  }
57 
58 public:
59  static char ID;
60 
61  /// Default construct and initialize the pass.
62  X86DiscriminateMemOps();
63 };
64 
65 } // end anonymous namespace
66 
67 //===----------------------------------------------------------------------===//
68 // Implementation
69 //===----------------------------------------------------------------------===//
70 
72 
73 /// Default construct and initialize the pass.
74 X86DiscriminateMemOps::X86DiscriminateMemOps() : MachineFunctionPass(ID) {}
75 
76 bool X86DiscriminateMemOps::runOnMachineFunction(MachineFunction &MF) {
78  return false;
79 
81  if (!FDI || !FDI->getUnit()->getDebugInfoForProfiling())
82  return false;
83 
84  // Have a default DILocation, if we find instructions with memops that don't
85  // have any debug info.
86  const DILocation *ReferenceDI =
87  DILocation::get(FDI->getContext(), FDI->getLine(), 0, FDI);
88  assert(ReferenceDI && "ReferenceDI should not be nullptr");
89  DenseMap<Location, unsigned> MemOpDiscriminators;
90  MemOpDiscriminators[diToLocation(ReferenceDI)] = 0;
91 
92  // Figure out the largest discriminator issued for each Location. When we
93  // issue new discriminators, we can thus avoid issuing discriminators
94  // belonging to instructions that don't have memops. This isn't a requirement
95  // for the goals of this pass, however, it avoids unnecessary ambiguity.
96  for (auto &MBB : MF) {
97  for (auto &MI : MBB) {
98  const auto &DI = MI.getDebugLoc();
99  if (!DI)
100  continue;
101  Location Loc = diToLocation(DI);
102  MemOpDiscriminators[Loc] =
103  std::max(MemOpDiscriminators[Loc], DI->getBaseDiscriminator());
104  }
105  }
106 
107  // Keep track of the discriminators seen at each Location. If an instruction's
108  // DebugInfo has a Location and discriminator we've already seen, replace its
109  // discriminator with a new one, to guarantee uniqueness.
111 
112  bool Changed = false;
113  for (auto &MBB : MF) {
114  for (auto &MI : MBB) {
115  if (X86II::getMemoryOperandNo(MI.getDesc().TSFlags) < 0)
116  continue;
117  const DILocation *DI = MI.getDebugLoc();
118  if (!DI) {
119  DI = ReferenceDI;
120  }
121  Location L = diToLocation(DI);
122  DenseSet<unsigned> &Set = Seen[L];
123  const std::pair<DenseSet<unsigned>::iterator, bool> TryInsert =
124  Set.insert(DI->getBaseDiscriminator());
125  if (!TryInsert.second) {
126  unsigned BF, DF, CI = 0;
127  DILocation::decodeDiscriminator(DI->getDiscriminator(), BF, DF, CI);
128  Optional<unsigned> EncodedDiscriminator = DILocation::encodeDiscriminator(
129  MemOpDiscriminators[L] + 1, DF, CI);
130 
131  if (!EncodedDiscriminator) {
132  // FIXME(mtrofin): The assumption is that this scenario is infrequent/OK
133  // not to support. If evidence points otherwise, we can explore synthesizeing
134  // unique DIs by adding fake line numbers, or by constructing 64 bit
135  // discriminators.
136  LLVM_DEBUG(dbgs() << "Unable to create a unique discriminator "
137  "for instruction with memory operand in: "
138  << DI->getFilename() << " Line: " << DI->getLine()
139  << " Column: " << DI->getColumn()
140  << ". This is likely due to a large macro expansion. \n");
141  continue;
142  }
143  // Since we were able to encode, bump the MemOpDiscriminators.
144  ++MemOpDiscriminators[L];
145  DI = DI->cloneWithDiscriminator(EncodedDiscriminator.getValue());
146  assert(DI && "DI should not be nullptr");
147  updateDebugInfo(&MI, DI);
148  Changed = true;
149  std::pair<DenseSet<unsigned>::iterator, bool> MustInsert =
150  Set.insert(DI->getBaseDiscriminator());
151  (void)MustInsert; // Silence warning in release build.
152  assert(MustInsert.second && "New discriminator shouldn't be present in set");
153  }
154 
155  // Bump the reference DI to avoid cramming discriminators on line 0.
156  // FIXME(mtrofin): pin ReferenceDI on blocks or first instruction with DI
157  // in a block. It's more consistent than just relying on the last memop
158  // instruction we happened to see.
159  ReferenceDI = DI;
160  }
161  }
162  return Changed;
163 }
164 
166  return new X86DiscriminateMemOps();
167 }
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A debug info location.
Definition: DebugLoc.h:33
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:422
DISubprogram * getSubprogram() const
Get the attached subprogram.
Definition: Metadata.cpp:1507
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)
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:696