blob: 5653babedf8eccd67fcb41be29fd61c377c6000a [file] [log] [blame]
Mircea Trofinf1a49e82018-11-30 01:01:52 +00001//===- X86DiscriminateMemOps.cpp - Unique IDs for Mem Ops -----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// This pass aids profile-driven cache prefetch insertion by ensuring all
11/// instructions that have a memory operand are distinguishible from each other.
12///
13//===----------------------------------------------------------------------===//
14
15#include "X86.h"
16#include "X86InstrBuilder.h"
17#include "X86InstrInfo.h"
18#include "X86MachineFunctionInfo.h"
19#include "X86Subtarget.h"
20#include "llvm/CodeGen/MachineModuleInfo.h"
21#include "llvm/IR/DebugInfoMetadata.h"
22#include "llvm/ProfileData/SampleProf.h"
23#include "llvm/ProfileData/SampleProfReader.h"
24#include "llvm/Transforms/IPO/SampleProfile.h"
25using namespace llvm;
26
Mircea Trofin41c729e2018-12-13 19:40:59 +000027#define DEBUG_TYPE "x86-discriminate-memops"
28
Mircea Trofinf1a49e82018-11-30 01:01:52 +000029namespace {
30
31using Location = std::pair<StringRef, unsigned>;
32
33Location diToLocation(const DILocation *Loc) {
34 return std::make_pair(Loc->getFilename(), Loc->getLine());
35}
36
37/// Ensure each instruction having a memory operand has a distinct <LineNumber,
38/// Discriminator> pair.
39void updateDebugInfo(MachineInstr *MI, const DILocation *Loc) {
40 DebugLoc DL(Loc);
41 MI->setDebugLoc(DL);
42}
43
44class X86DiscriminateMemOps : public MachineFunctionPass {
45 bool runOnMachineFunction(MachineFunction &MF) override;
46 StringRef getPassName() const override {
47 return "X86 Discriminate Memory Operands";
48 }
49
50public:
51 static char ID;
52
53 /// Default construct and initialize the pass.
54 X86DiscriminateMemOps();
55};
56
57} // end anonymous namespace
58
59//===----------------------------------------------------------------------===//
60// Implementation
61//===----------------------------------------------------------------------===//
62
63char X86DiscriminateMemOps::ID = 0;
64
65/// Default construct and initialize the pass.
66X86DiscriminateMemOps::X86DiscriminateMemOps() : MachineFunctionPass(ID) {}
67
68bool X86DiscriminateMemOps::runOnMachineFunction(MachineFunction &MF) {
69 DISubprogram *FDI = MF.getFunction().getSubprogram();
70 if (!FDI || !FDI->getUnit()->getDebugInfoForProfiling())
71 return false;
72
73 // Have a default DILocation, if we find instructions with memops that don't
74 // have any debug info.
75 const DILocation *ReferenceDI =
76 DILocation::get(FDI->getContext(), FDI->getLine(), 0, FDI);
77
78 DenseMap<Location, unsigned> MemOpDiscriminators;
79 MemOpDiscriminators[diToLocation(ReferenceDI)] = 0;
80
81 // Figure out the largest discriminator issued for each Location. When we
82 // issue new discriminators, we can thus avoid issuing discriminators
83 // belonging to instructions that don't have memops. This isn't a requirement
84 // for the goals of this pass, however, it avoids unnecessary ambiguity.
85 for (auto &MBB : MF) {
86 for (auto &MI : MBB) {
87 const auto &DI = MI.getDebugLoc();
88 if (!DI)
89 continue;
90 Location Loc = diToLocation(DI);
91 MemOpDiscriminators[Loc] =
92 std::max(MemOpDiscriminators[Loc], DI->getBaseDiscriminator());
93 }
94 }
95
96 // Keep track of the discriminators seen at each Location. If an instruction's
97 // DebugInfo has a Location and discriminator we've already seen, replace its
98 // discriminator with a new one, to guarantee uniqueness.
99 DenseMap<Location, DenseSet<unsigned>> Seen;
100
101 bool Changed = false;
102 for (auto &MBB : MF) {
103 for (auto &MI : MBB) {
104 if (X86II::getMemoryOperandNo(MI.getDesc().TSFlags) < 0)
105 continue;
106 const DILocation *DI = MI.getDebugLoc();
107 if (!DI) {
108 DI = ReferenceDI;
109 }
110 DenseSet<unsigned> &Set = Seen[diToLocation(DI)];
111 const std::pair<DenseSet<unsigned>::iterator, bool> TryInsert =
112 Set.insert(DI->getBaseDiscriminator());
113 if (!TryInsert.second) {
114 DI = DI->setBaseDiscriminator(++MemOpDiscriminators[diToLocation(DI)]);
115 updateDebugInfo(&MI, DI);
116 Changed = true;
117 const std::pair<DenseSet<unsigned>::iterator, bool> MustInsert =
118 Set.insert(DI->getBaseDiscriminator());
Mircea Trofin41c729e2018-12-13 19:40:59 +0000119 // FIXME (mtrofin): check if the to-be inserted base discriminator can
120 // be added. This requires a new API on DILocation.
121 // The assumption is that this scenario is infrequent/OK not to support.
122 // If evidence points otherwise, we can explore synthesize unique DIs by
123 // adding fake line numbers.
124 if (!MustInsert.second) {
125 LLVM_DEBUG(dbgs()
126 << "Unable to create a unique discriminator in "
127 << DI->getFilename() << " Line: " << DI->getLine()
128 << " Column: " << DI->getColumn()
129 << ". This is likely due to a large macro expansion.\n");
130 }
Mircea Trofinf1a49e82018-11-30 01:01:52 +0000131 }
132
133 // Bump the reference DI to avoid cramming discriminators on line 0.
134 // FIXME(mtrofin): pin ReferenceDI on blocks or first instruction with DI
135 // in a block. It's more consistent than just relying on the last memop
136 // instruction we happened to see.
137 ReferenceDI = DI;
138 }
139 }
140 return Changed;
141}
142
143FunctionPass *llvm::createX86DiscriminateMemOpsPass() {
144 return new X86DiscriminateMemOps();
145}