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