1 //===- 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" 25 using namespace llvm; 26 27 namespace { 28 29 using Location = std::pair<StringRef, unsigned>; 30 31 Location 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. 37 void updateDebugInfo(MachineInstr *MI, const DILocation *Loc) { 38 DebugLoc DL(Loc); 39 MI->setDebugLoc(DL); 40 } 41 42 class X86DiscriminateMemOps : public MachineFunctionPass { 43 bool runOnMachineFunction(MachineFunction &MF) override; 44 StringRef getPassName() const override { 45 return "X86 Discriminate Memory Operands"; 46 } 47 48 public: 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 61 char X86DiscriminateMemOps::ID = 0; 62 63 /// Default construct and initialize the pass. 64 X86DiscriminateMemOps::X86DiscriminateMemOps() : MachineFunctionPass(ID) {} 65 66 bool 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 (void)MustInsert; // silence warning. 118 assert(MustInsert.second && 119 "New discriminator shouldn't be present in set"); 120 } 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 132 FunctionPass *llvm::createX86DiscriminateMemOpsPass() { 133 return new X86DiscriminateMemOps(); 134 } 135