blob: 4935896abfe799bca8cc796948f79ed9b4e3b585 [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
27namespace {
28
29using Location = std::pair<StringRef, unsigned>;
30
31Location diToLocation(const DILocation *Loc) {
32 return std::make_pair(Loc->getFilename(), Loc->getLine());
33}
34
35/// Ensure each instruction having a memory operand has a distinct <LineNumber,
36/// Discriminator> pair.
37void updateDebugInfo(MachineInstr *MI, const DILocation *Loc) {
38 DebugLoc DL(Loc);
39 MI->setDebugLoc(DL);
40}
41
42class X86DiscriminateMemOps : public MachineFunctionPass {
43 bool runOnMachineFunction(MachineFunction &MF) override;
44 StringRef getPassName() const override {
45 return "X86 Discriminate Memory Operands";
46 }
47
48public:
49 static char ID;
50
51 /// Default construct and initialize the pass.
52 X86DiscriminateMemOps();
53};
54
55} // end anonymous namespace
56
57//===----------------------------------------------------------------------===//
58// Implementation
59//===----------------------------------------------------------------------===//
60
61char X86DiscriminateMemOps::ID = 0;
62
63/// Default construct and initialize the pass.
64X86DiscriminateMemOps::X86DiscriminateMemOps() : MachineFunctionPass(ID) {}
65
66bool X86DiscriminateMemOps::runOnMachineFunction(MachineFunction &MF) {
67 DISubprogram *FDI = MF.getFunction().getSubprogram();
68 if (!FDI || !FDI->getUnit()->getDebugInfoForProfiling())
69 return false;
70
71 // Have a default DILocation, if we find instructions with memops that don't
72 // have any debug info.
73 const DILocation *ReferenceDI =
74 DILocation::get(FDI->getContext(), FDI->getLine(), 0, FDI);
75
76 DenseMap<Location, unsigned> MemOpDiscriminators;
77 MemOpDiscriminators[diToLocation(ReferenceDI)] = 0;
78
79 // Figure out the largest discriminator issued for each Location. When we
80 // issue new discriminators, we can thus avoid issuing discriminators
81 // belonging to instructions that don't have memops. This isn't a requirement
82 // for the goals of this pass, however, it avoids unnecessary ambiguity.
83 for (auto &MBB : MF) {
84 for (auto &MI : MBB) {
85 const auto &DI = MI.getDebugLoc();
86 if (!DI)
87 continue;
88 Location Loc = diToLocation(DI);
89 MemOpDiscriminators[Loc] =
90 std::max(MemOpDiscriminators[Loc], DI->getBaseDiscriminator());
91 }
92 }
93
94 // Keep track of the discriminators seen at each Location. If an instruction's
95 // DebugInfo has a Location and discriminator we've already seen, replace its
96 // discriminator with a new one, to guarantee uniqueness.
97 DenseMap<Location, DenseSet<unsigned>> Seen;
98
99 bool Changed = false;
100 for (auto &MBB : MF) {
101 for (auto &MI : MBB) {
102 if (X86II::getMemoryOperandNo(MI.getDesc().TSFlags) < 0)
103 continue;
104 const DILocation *DI = MI.getDebugLoc();
105 if (!DI) {
106 DI = ReferenceDI;
107 }
108 DenseSet<unsigned> &Set = Seen[diToLocation(DI)];
109 const std::pair<DenseSet<unsigned>::iterator, bool> TryInsert =
110 Set.insert(DI->getBaseDiscriminator());
111 if (!TryInsert.second) {
112 DI = DI->setBaseDiscriminator(++MemOpDiscriminators[diToLocation(DI)]);
113 updateDebugInfo(&MI, DI);
114 Changed = true;
115 const std::pair<DenseSet<unsigned>::iterator, bool> MustInsert =
116 Set.insert(DI->getBaseDiscriminator());
117 assert(MustInsert.second);
118 }
119
120 // Bump the reference DI to avoid cramming discriminators on line 0.
121 // FIXME(mtrofin): pin ReferenceDI on blocks or first instruction with DI
122 // in a block. It's more consistent than just relying on the last memop
123 // instruction we happened to see.
124 ReferenceDI = DI;
125 }
126 }
127 return Changed;
128}
129
130FunctionPass *llvm::createX86DiscriminateMemOpsPass() {
131 return new X86DiscriminateMemOps();
132}