blob: 4ab32ab53e5493065d7ab1698f8c210e2672c5e0 [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());
Mircea Trofin5e0b21f2018-11-30 01:53:17 +0000117 (void)MustInsert; // silence warning.
118 assert(MustInsert.second &&
119 "New discriminator shouldn't be present in set");
Mircea Trofinf1a49e82018-11-30 01:01:52 +0000120 }
121
122 // Bump the reference DI to avoid cramming discriminators on line 0.
123 // FIXME(mtrofin): pin ReferenceDI on blocks or first instruction with DI
124 // in a block. It's more consistent than just relying on the last memop
125 // instruction we happened to see.
126 ReferenceDI = DI;
127 }
128 }
129 return Changed;
130}
131
132FunctionPass *llvm::createX86DiscriminateMemOpsPass() {
133 return new X86DiscriminateMemOps();
134}