blob: fcb7402d7861a9327a313eec91f6eaff6908f710 [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"
Mircea Trofinb53eeb62018-12-21 22:48:50 +000024#include "llvm/Support/Debug.h"
Mircea Trofinf1a49e82018-11-30 01:01:52 +000025#include "llvm/Transforms/IPO/SampleProfile.h"
26using namespace llvm;
27
Mircea Trofin41c729e2018-12-13 19:40:59 +000028#define DEBUG_TYPE "x86-discriminate-memops"
29
Mircea Trofinf1a49e82018-11-30 01:01:52 +000030namespace {
31
32using Location = std::pair<StringRef, unsigned>;
33
34Location diToLocation(const DILocation *Loc) {
35 return std::make_pair(Loc->getFilename(), Loc->getLine());
36}
37
38/// Ensure each instruction having a memory operand has a distinct <LineNumber,
39/// Discriminator> pair.
40void updateDebugInfo(MachineInstr *MI, const DILocation *Loc) {
41 DebugLoc DL(Loc);
42 MI->setDebugLoc(DL);
43}
44
45class X86DiscriminateMemOps : public MachineFunctionPass {
46 bool runOnMachineFunction(MachineFunction &MF) override;
47 StringRef getPassName() const override {
48 return "X86 Discriminate Memory Operands";
49 }
50
51public:
52 static char ID;
53
54 /// Default construct and initialize the pass.
55 X86DiscriminateMemOps();
56};
57
58} // end anonymous namespace
59
60//===----------------------------------------------------------------------===//
61// Implementation
62//===----------------------------------------------------------------------===//
63
64char X86DiscriminateMemOps::ID = 0;
65
66/// Default construct and initialize the pass.
67X86DiscriminateMemOps::X86DiscriminateMemOps() : MachineFunctionPass(ID) {}
68
69bool X86DiscriminateMemOps::runOnMachineFunction(MachineFunction &MF) {
70 DISubprogram *FDI = MF.getFunction().getSubprogram();
71 if (!FDI || !FDI->getUnit()->getDebugInfoForProfiling())
72 return false;
73
74 // Have a default DILocation, if we find instructions with memops that don't
75 // have any debug info.
76 const DILocation *ReferenceDI =
77 DILocation::get(FDI->getContext(), FDI->getLine(), 0, FDI);
78
79 DenseMap<Location, unsigned> MemOpDiscriminators;
80 MemOpDiscriminators[diToLocation(ReferenceDI)] = 0;
81
82 // Figure out the largest discriminator issued for each Location. When we
83 // issue new discriminators, we can thus avoid issuing discriminators
84 // belonging to instructions that don't have memops. This isn't a requirement
85 // for the goals of this pass, however, it avoids unnecessary ambiguity.
86 for (auto &MBB : MF) {
87 for (auto &MI : MBB) {
88 const auto &DI = MI.getDebugLoc();
89 if (!DI)
90 continue;
91 Location Loc = diToLocation(DI);
92 MemOpDiscriminators[Loc] =
93 std::max(MemOpDiscriminators[Loc], DI->getBaseDiscriminator());
94 }
95 }
96
97 // Keep track of the discriminators seen at each Location. If an instruction's
98 // DebugInfo has a Location and discriminator we've already seen, replace its
99 // discriminator with a new one, to guarantee uniqueness.
100 DenseMap<Location, DenseSet<unsigned>> Seen;
101
102 bool Changed = false;
103 for (auto &MBB : MF) {
104 for (auto &MI : MBB) {
105 if (X86II::getMemoryOperandNo(MI.getDesc().TSFlags) < 0)
106 continue;
107 const DILocation *DI = MI.getDebugLoc();
108 if (!DI) {
109 DI = ReferenceDI;
110 }
Mircea Trofinb53eeb62018-12-21 22:48:50 +0000111 Location L = diToLocation(DI);
112 DenseSet<unsigned> &Set = Seen[L];
Mircea Trofinf1a49e82018-11-30 01:01:52 +0000113 const std::pair<DenseSet<unsigned>::iterator, bool> TryInsert =
114 Set.insert(DI->getBaseDiscriminator());
115 if (!TryInsert.second) {
Mircea Trofinb53eeb62018-12-21 22:48:50 +0000116 unsigned BF, DF, CI = 0;
117 DILocation::decodeDiscriminator(DI->getDiscriminator(), BF, DF, CI);
118 Optional<unsigned> EncodedDiscriminator = DILocation::encodeDiscriminator(
119 MemOpDiscriminators[L] + 1, DF, CI);
120
121 if (!EncodedDiscriminator) {
122 // FIXME(mtrofin): The assumption is that this scenario is infrequent/OK
123 // not to support. If evidence points otherwise, we can explore synthesizeing
124 // unique DIs by adding fake line numbers, or by constructing 64 bit
125 // discriminators.
126 LLVM_DEBUG(dbgs() << "Unable to create a unique discriminator "
127 "for instruction with memory operand in: "
Mircea Trofin41c729e2018-12-13 19:40:59 +0000128 << DI->getFilename() << " Line: " << DI->getLine()
129 << " Column: " << DI->getColumn()
Mircea Trofinb53eeb62018-12-21 22:48:50 +0000130 << ". This is likely due to a large macro expansion. \n");
131 continue;
Mircea Trofin41c729e2018-12-13 19:40:59 +0000132 }
Mircea Trofinb53eeb62018-12-21 22:48:50 +0000133 // Since we were able to encode, bump the MemOpDiscriminators.
134 ++MemOpDiscriminators[L];
135 DI = DI->cloneWithDiscriminator(EncodedDiscriminator.getValue());
136 updateDebugInfo(&MI, DI);
137 Changed = true;
138 std::pair<DenseSet<unsigned>::iterator, bool> MustInsert =
139 Set.insert(DI->getBaseDiscriminator());
140 assert(MustInsert.second && "New discriminator shouldn't be present in set");
Mircea Trofinf1a49e82018-11-30 01:01:52 +0000141 }
142
143 // Bump the reference DI to avoid cramming discriminators on line 0.
144 // FIXME(mtrofin): pin ReferenceDI on blocks or first instruction with DI
145 // in a block. It's more consistent than just relying on the last memop
146 // instruction we happened to see.
147 ReferenceDI = DI;
148 }
149 }
150 return Changed;
151}
152
153FunctionPass *llvm::createX86DiscriminateMemOpsPass() {
154 return new X86DiscriminateMemOps();
155}