Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/X86/X86DiscriminateMemOps.cpp
Line
Count
Source (jump to first uncovered line)
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"
19
#include "llvm/CodeGen/MachineModuleInfo.h"
20
#include "llvm/IR/DebugInfoMetadata.h"
21
#include "llvm/ProfileData/SampleProf.h"
22
#include "llvm/ProfileData/SampleProfReader.h"
23
#include "llvm/Support/Debug.h"
24
#include "llvm/Transforms/IPO/SampleProfile.h"
25
using namespace llvm;
26
27
#define DEBUG_TYPE "x86-discriminate-memops"
28
29
static cl::opt<bool> EnableDiscriminateMemops(
30
    DEBUG_TYPE, cl::init(false),
31
    cl::desc("Generate unique debug info for each instruction with a memory "
32
             "operand. Should be enabled for profile-drived cache prefetching, "
33
             "both in the build of the binary being profiled, as well as in "
34
             "the build of the binary consuming the profile."),
35
    cl::Hidden);
36
37
static cl::opt<bool> BypassPrefetchInstructions(
38
    "x86-bypass-prefetch-instructions", cl::init(true),
39
    cl::desc("When discriminating instructions with memory operands, ignore "
40
             "prefetch instructions. This ensures the other memory operand "
41
             "instructions have the same identifiers after inserting "
42
             "prefetches, allowing for successive insertions."),
43
    cl::Hidden);
44
45
namespace {
46
47
using Location = std::pair<StringRef, unsigned>;
48
49
65
Location diToLocation(const DILocation *Loc) {
50
65
  return std::make_pair(Loc->getFilename(), Loc->getLine());
51
65
}
52
53
/// Ensure each instruction having a memory operand has a distinct <LineNumber,
54
/// Discriminator> pair.
55
9
void updateDebugInfo(MachineInstr *MI, const DILocation *Loc) {
56
9
  DebugLoc DL(Loc);
57
9
  MI->setDebugLoc(DL);
58
9
}
59
60
class X86DiscriminateMemOps : public MachineFunctionPass {
61
  bool runOnMachineFunction(MachineFunction &MF) override;
62
150k
  StringRef getPassName() const override {
63
150k
    return "X86 Discriminate Memory Operands";
64
150k
  }
65
66
public:
67
  static char ID;
68
69
  /// Default construct and initialize the pass.
70
  X86DiscriminateMemOps();
71
};
72
73
51
bool IsPrefetchOpcode(unsigned Opcode) {
74
51
  return Opcode == X86::PREFETCHNTA || 
Opcode == X86::PREFETCHT049
||
75
51
         
Opcode == X86::PREFETCHT148
||
Opcode == X86::PREFETCHT248
;
76
51
}
77
} // end anonymous namespace
78
79
//===----------------------------------------------------------------------===//
80
//            Implementation
81
//===----------------------------------------------------------------------===//
82
83
char X86DiscriminateMemOps::ID = 0;
84
85
/// Default construct and initialize the pass.
86
12.2k
X86DiscriminateMemOps::X86DiscriminateMemOps() : MachineFunctionPass(ID) {}
87
88
137k
bool X86DiscriminateMemOps::runOnMachineFunction(MachineFunction &MF) {
89
137k
  if (!EnableDiscriminateMemops)
90
137k
    return false;
91
20
92
20
  DISubprogram *FDI = MF.getFunction().getSubprogram();
93
20
  if (!FDI || 
!FDI->getUnit()->getDebugInfoForProfiling()9
)
94
0
    return false;
95
20
96
20
  // Have a default DILocation, if we find instructions with memops that don't
97
20
  // have any debug info.
98
20
  const DILocation *ReferenceDI =
99
20
      DILocation::get(FDI->getContext(), FDI->getLine(), 0, FDI);
100
20
  assert(ReferenceDI && "ReferenceDI should not be nullptr");
101
20
  DenseMap<Location, unsigned> MemOpDiscriminators;
102
20
  MemOpDiscriminators[diToLocation(ReferenceDI)] = 0;
103
20
104
20
  // Figure out the largest discriminator issued for each Location. When we
105
20
  // issue new discriminators, we can thus avoid issuing discriminators
106
20
  // belonging to instructions that don't have memops. This isn't a requirement
107
20
  // for the goals of this pass, however, it avoids unnecessary ambiguity.
108
20
  for (auto &MBB : MF) {
109
48
    for (auto &MI : MBB) {
110
48
      const auto &DI = MI.getDebugLoc();
111
48
      if (!DI)
112
9
        continue;
113
39
      if (BypassPrefetchInstructions && 
IsPrefetchOpcode(MI.getDesc().Opcode)34
)
114
1
        continue;
115
38
      Location Loc = diToLocation(DI);
116
38
      MemOpDiscriminators[Loc] =
117
38
          std::max(MemOpDiscriminators[Loc], DI->getBaseDiscriminator());
118
38
    }
119
9
  }
120
20
121
20
  // Keep track of the discriminators seen at each Location. If an instruction's
122
20
  // DebugInfo has a Location and discriminator we've already seen, replace its
123
20
  // discriminator with a new one, to guarantee uniqueness.
124
20
  DenseMap<Location, DenseSet<unsigned>> Seen;
125
20
126
20
  bool Changed = false;
127
20
  for (auto &MBB : MF) {
128
48
    for (auto &MI : MBB) {
129
48
      if (X86II::getMemoryOperandNo(MI.getDesc().TSFlags) < 0)
130
28
        continue;
131
20
      if (BypassPrefetchInstructions && 
IsPrefetchOpcode(MI.getDesc().Opcode)17
)
132
2
        continue;
133
18
      const DILocation *DI = MI.getDebugLoc();
134
18
      bool HasDebug = DI;
135
18
      if (!HasDebug) {
136
2
        DI = ReferenceDI;
137
2
      }
138
18
      Location L = diToLocation(DI);
139
18
      DenseSet<unsigned> &Set = Seen[L];
140
18
      const std::pair<DenseSet<unsigned>::iterator, bool> TryInsert =
141
18
          Set.insert(DI->getBaseDiscriminator());
142
18
      if (!TryInsert.second || 
!HasDebug11
) {
143
9
        unsigned BF, DF, CI = 0;
144
9
        DILocation::decodeDiscriminator(DI->getDiscriminator(), BF, DF, CI);
145
9
        Optional<unsigned> EncodedDiscriminator = DILocation::encodeDiscriminator(
146
9
            MemOpDiscriminators[L] + 1, DF, CI);
147
9
148
9
        if (!EncodedDiscriminator) {
149
0
          // FIXME(mtrofin): The assumption is that this scenario is infrequent/OK
150
0
          // not to support. If evidence points otherwise, we can explore synthesizeing
151
0
          // unique DIs by adding fake line numbers, or by constructing 64 bit
152
0
          // discriminators.
153
0
          LLVM_DEBUG(dbgs() << "Unable to create a unique discriminator "
154
0
                     "for instruction with memory operand in: "
155
0
                     << DI->getFilename() << " Line: " << DI->getLine()
156
0
                     << " Column: " << DI->getColumn()
157
0
                     << ". This is likely due to a large macro expansion. \n");
158
0
          continue;
159
0
        }
160
9
        // Since we were able to encode, bump the MemOpDiscriminators.
161
9
        ++MemOpDiscriminators[L];
162
9
        DI = DI->cloneWithDiscriminator(EncodedDiscriminator.getValue());
163
9
        assert(DI && "DI should not be nullptr");
164
9
        updateDebugInfo(&MI, DI);
165
9
        Changed = true;
166
9
        std::pair<DenseSet<unsigned>::iterator, bool> MustInsert =
167
9
            Set.insert(DI->getBaseDiscriminator());
168
9
        (void)MustInsert; // Silence warning in release build.
169
9
        assert(MustInsert.second && "New discriminator shouldn't be present in set");
170
9
      }
171
18
172
18
      // Bump the reference DI to avoid cramming discriminators on line 0.
173
18
      // FIXME(mtrofin): pin ReferenceDI on blocks or first instruction with DI
174
18
      // in a block. It's more consistent than just relying on the last memop
175
18
      // instruction we happened to see.
176
18
      ReferenceDI = DI;
177
18
    }
178
9
  }
179
20
  return Changed;
180
20
}
181
182
12.2k
FunctionPass *llvm::createX86DiscriminateMemOpsPass() {
183
12.2k
  return new X86DiscriminateMemOps();
184
12.2k
}